summaryrefslogtreecommitdiffstats
path: root/media/mca
diff options
context:
space:
mode:
authorRuei-sung Lin <rslin@google.com>2012-05-15 10:25:55 -0700
committerRuei-sung Lin <rslin@google.com>2012-05-29 15:52:45 -0700
commit0a1013229254cdc146d4ce2f4b4aef301b018f09 (patch)
treebe391369af2c3e8c4c90b739e7dffcb71152933a /media/mca
parent9d820eccfc2ddbdc03680e22b9d4c4cac66a97b9 (diff)
downloadframeworks_base-0a1013229254cdc146d4ce2f4b4aef301b018f09.zip
frameworks_base-0a1013229254cdc146d4ce2f4b4aef301b018f09.tar.gz
frameworks_base-0a1013229254cdc146d4ce2f4b4aef301b018f09.tar.bz2
Fix b/6575950 make shader program to support different precisions.
1. In shade code of Vignette and Fisheye, change from pixel coordinates to texture coordinates to avoid overflow. 2. Fix bug in ColorTemperature shader code 3. Revise shader code pseudo random number generator (used by BlackWhite, Grain, Lomo, Documentary filters) to ensure it produces no artifacts among devices with different precisions. Change-Id: Ifb67f12f114bc9cd7fbfa74f7782f130c5244e5d
Diffstat (limited to 'media/mca')
-rw-r--r--media/mca/filterpacks/java/android/filterpacks/imageproc/BlackWhiteFilter.java26
-rw-r--r--media/mca/filterpacks/java/android/filterpacks/imageproc/ColorTemperatureFilter.java2
-rw-r--r--media/mca/filterpacks/java/android/filterpacks/imageproc/DocumentaryFilter.java38
-rw-r--r--media/mca/filterpacks/java/android/filterpacks/imageproc/FisheyeFilter.java39
-rw-r--r--media/mca/filterpacks/java/android/filterpacks/imageproc/GrainFilter.java16
-rw-r--r--media/mca/filterpacks/java/android/filterpacks/imageproc/LomoishFilter.java38
-rw-r--r--media/mca/filterpacks/java/android/filterpacks/imageproc/VignetteFilter.java23
7 files changed, 106 insertions, 76 deletions
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/BlackWhiteFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/BlackWhiteFilter.java
index dd7f5e0..20b02d2 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/BlackWhiteFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/BlackWhiteFilter.java
@@ -56,13 +56,25 @@ public class BlackWhiteFilter extends Filter {
"uniform float stepsize;\n" +
"varying vec2 v_texcoord;\n" +
"float rand(vec2 loc) {\n" +
- " const float divide = 0.00048828125;\n" +
- " const float factor = 2048.0;\n" +
- " float value = sin(dot(loc, vec2(12.9898, 78.233)));\n" +
- " float residual = mod(dot(mod(loc, divide), vec2(0.9898, 0.233)), divide);\n" +
- " float part2 = mod(value, divide);\n" +
- " float part1 = value - part2;\n" +
- " return fract(0.5453 * part1 + factor * (part2 + residual));\n" +
+ // Compute sin(theta), theta = 12.9898 x + 78.233y
+ // because floating point has limited range, make theta = theta1 + theta2
+ // where theta1 = 12x + 78y and theta2 = 0.9898x + 0.233y)
+ // Note that theta1 and theta2 cover diffent range of theta.
+ " float theta1 = dot(loc, vec2(0.9898, 0.233));\n" +
+ " float theta2 = dot(loc, vec2(12.0, 78.0));\n" +
+ // Use the property sin(theta) = cos(theta1)*sin(theta2)+sin(theta1)*cos(theta2)
+ // this approach also increases the precisions of sin(theta)
+ " float value = cos(theta1) * sin(theta2) + sin(theta1) * cos(theta2);\n" +
+ // fract(43758.5453 * x) = fract(43758 * x + 0.5453 * x)
+ // keep value of part1 in range: (2^-14 to 2^14). Since 43758 = 117 * 374
+ // fract(43758 * sin(theta)) = mod(221 * mod(198*sin(theta), 1.0), 1.0)
+ // also to keep as much decimal digits, use the property
+ // mod(mod(198*sin(theta)) = mod(mod(197*sin(theta) + sin(theta))
+ " 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" +
" vec4 color = texture2D(tex_sampler_0, v_texcoord);\n" +
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/ColorTemperatureFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/ColorTemperatureFilter.java
index 19da006..7488980 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/ColorTemperatureFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/ColorTemperatureFilter.java
@@ -51,7 +51,7 @@ public class ColorTemperatureFilter extends Filter {
" new_color.r = color.r + color.r * ( 1.0 - color.r) * scale;\n" +
" new_color.b = color.b - color.b * ( 1.0 - color.b) * scale;\n" +
" if (scale > 0.0) { \n" +
- " color.g = color.g + color.g * ( 1.0 - color.g) * scale * 0.25;\n" +
+ " new_color.g = color.g + color.g * ( 1.0 - color.g) * scale * 0.25;\n" +
" }\n" +
" float max_value = max(new_color.r, max(new_color.g, new_color.b));\n" +
" if (max_value > 1.0) { \n" +
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/DocumentaryFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/DocumentaryFilter.java
index 377e49d..f93a82c 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/DocumentaryFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/DocumentaryFilter.java
@@ -49,16 +49,18 @@ public class DocumentaryFilter extends Filter {
"uniform vec2 seed;\n" +
"uniform float stepsize;\n" +
"uniform float inv_max_dist;\n" +
- "uniform vec2 center;\n" +
+ "uniform vec2 scale;\n" +
"varying vec2 v_texcoord;\n" +
"float rand(vec2 loc) {\n" +
- " const float divide = 0.00048828125;\n" +
- " const float factor = 2048.0;\n" +
- " float value = sin(dot(loc, vec2(12.9898, 78.233)));\n" +
- " float residual = mod(dot(mod(loc, divide), vec2(0.9898, 0.233)), divide);\n" +
- " float part2 = mod(value, divide);\n" +
- " float part1 = value - part2;\n" +
- " return fract(0.5453 * part1 + factor * (part2 + residual));\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" +
// black white
@@ -71,7 +73,8 @@ public class DocumentaryFilter extends Filter {
" float gray = dot(new_color, vec3(0.299, 0.587, 0.114));\n" +
" new_color = vec3(gray, gray, gray);\n" +
// vignette
- " float dist = distance(gl_FragCoord.xy, center);\n" +
+ " vec2 coord = v_texcoord - 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";
@@ -141,12 +144,17 @@ public class DocumentaryFilter extends Filter {
private void initParameters() {
if (mProgram != null) {
- float centerX = (float) (0.5 * mWidth);
- float centerY = (float) (0.5 * mHeight);
- float center[] = {centerX, centerY};
- float max_dist = (float) Math.sqrt(centerX * centerX + centerY * centerY);
-
- mProgram.setHostValue("center", center);
+ float scale[] = new float[2];
+ if (mWidth > mHeight) {
+ scale[0] = 1f;
+ scale[1] = ((float) mHeight) / mWidth;
+ } else {
+ scale[0] = ((float) mWidth) / mHeight;
+ scale[1] = 1f;
+ }
+ float max_dist = ((float) Math.sqrt(scale[0] * scale[0] + scale[1] * scale[1])) * 0.5f;
+
+ mProgram.setHostValue("scale", scale);
mProgram.setHostValue("inv_max_dist", 1.0f / max_dist);
mProgram.setHostValue("stepsize", 1.0f / 255.0f);
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/FisheyeFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/FisheyeFilter.java
index 8d38f98..5d7929f 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/FisheyeFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/FisheyeFilter.java
@@ -58,24 +58,19 @@ public class FisheyeFilter extends Filter {
private static final String mFisheyeShader =
"precision mediump float;\n" +
"uniform sampler2D tex_sampler_0;\n" +
- "uniform vec2 center;\n" +
+ "uniform vec2 scale;\n" +
"uniform float alpha;\n" +
- "uniform float bound;\n" +
"uniform float radius2;\n" +
"uniform float factor;\n" +
- "uniform float inv_height;\n" +
- "uniform float inv_width;\n" +
"varying vec2 v_texcoord;\n" +
"void main() {\n" +
" const float m_pi_2 = 1.570963;\n" +
- " float dist = distance(gl_FragCoord.xy, center);\n" +
+ " vec2 coord = v_texcoord - vec2(0.5, 0.5);\n" +
+ " float dist = length(coord * scale);\n" +
" float radian = m_pi_2 - atan(alpha * sqrt(radius2 - dist * dist), dist);\n" +
- " float scale = radian * factor / dist;\n" +
- " vec2 new_coord = gl_FragCoord.xy * scale + (1.0 - scale) * center;\n" +
- " new_coord.x *= inv_width;\n" +
- " new_coord.y *= inv_height;\n" +
- " vec4 color = texture2D(tex_sampler_0, new_coord);\n" +
- " gl_FragColor = color;\n" +
+ " float scalar = radian * factor / dist;\n" +
+ " vec2 new_coord = coord * scalar + vec2(0.5, 0.5);\n" +
+ " gl_FragColor = texture2D(tex_sampler_0, new_coord);\n" +
"}\n";
public FisheyeFilter(String name) {
@@ -145,12 +140,6 @@ public class FisheyeFilter extends Filter {
}
private void updateFrameSize(int width, int height) {
- float center[] = {0.5f * width, 0.5f * height};
-
- mProgram.setHostValue("center", center);
- mProgram.setHostValue("inv_width", 1.0f / width);
- mProgram.setHostValue("inv_height", 1.0f / height);
-
mWidth = width;
mHeight = height;
@@ -159,9 +148,16 @@ public class FisheyeFilter extends Filter {
private void updateProgramParams() {
final float pi = 3.14159265f;
-
+ float scale[] = new float[2];
+ if (mWidth > mHeight) {
+ scale[0] = 1f;
+ scale[1] = ((float) mHeight) / mWidth;
+ } else {
+ scale[0] = ((float) mWidth) / mHeight;
+ scale[1] = 1f;
+ }
float alpha = mScale * 2.0f + 0.75f;
- float bound2 = 0.25f * (mWidth * mWidth + mHeight * mHeight);
+ float bound2 = 0.25f * (scale[0] * scale[0] + scale[1] * scale[1]);
float bound = (float) Math.sqrt(bound2);
float radius = 1.15f * bound;
float radius2 = radius * radius;
@@ -169,10 +165,9 @@ public class FisheyeFilter extends Filter {
(float) Math.atan(alpha / bound * (float) Math.sqrt(radius2 - bound2));
float factor = bound / max_radian;
+ mProgram.setHostValue("scale", scale);
mProgram.setHostValue("radius2",radius2);
mProgram.setHostValue("factor", factor);
- mProgram.setHostValue("alpha", (float) (mScale * 2.0 + 0.75));
+ mProgram.setHostValue("alpha", alpha);
}
-
-
}
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/GrainFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/GrainFilter.java
index f236856..577243a 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/GrainFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/GrainFilter.java
@@ -57,13 +57,15 @@ public class GrainFilter extends Filter {
"uniform vec2 seed;\n" +
"varying vec2 v_texcoord;\n" +
"float rand(vec2 loc) {\n" +
- " const float divide = 0.00048828125;\n" +
- " const float factor = 2048.0;\n" +
- " float value = sin(dot(loc, vec2(12.9898, 78.233)));\n" +
- " float residual = mod(dot(mod(loc, divide), vec2(0.9898, 0.233)), divide);\n" +
- " float part2 = mod(value, divide);\n" +
- " float part1 = value - part2;\n" +
- " return fract(0.5453 * part1 + factor * (part2 + residual));\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" +
" gl_FragColor = vec4(rand(v_texcoord + seed), 0.0, 0.0, 1.0);\n" +
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/LomoishFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/LomoishFilter.java
index 22a2ec8..726ffff 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/LomoishFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/LomoishFilter.java
@@ -50,17 +50,19 @@ public class LomoishFilter extends Filter {
"uniform float stepsizeX;\n" +
"uniform float stepsizeY;\n" +
"uniform float stepsize;\n" +
- "uniform vec2 center;\n" +
+ "uniform vec2 scale;\n" +
"uniform float inv_max_dist;\n" +
"varying vec2 v_texcoord;\n" +
"float rand(vec2 loc) {\n" +
- " const float divide = 0.00048828125;\n" +
- " const float factor = 2048.0;\n" +
- " float value = sin(dot(loc, vec2(12.9898, 78.233)));\n" +
- " float residual = mod(dot(mod(loc, divide), vec2(0.9898, 0.233)), divide);\n" +
- " float part2 = mod(value, divide);\n" +
- " float part1 = value - part2;\n" +
- " return fract(0.5453 * part1 + factor * (part2 + residual));\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" +
// sharpen
@@ -112,7 +114,8 @@ public class LomoishFilter extends Filter {
" vec3 temp = clamp((color.rgb + stepsize - 0.15) * 1.53846, 0.0, 1.0);\n" +
" vec3 bw_color = clamp(xform + (temp - xform) * (dither - 0.5), 0.0, 1.0);\n" +
// vignette
- " float dist = distance(gl_FragCoord.xy, center);\n" +
+ " coord = v_texcoord - vec2(0.5, 0.5);\n" +
+ " float dist = length(coord * scale);\n" +
" float lumen = 0.85 / (1.0 + exp((dist * inv_max_dist - 0.73) * 20.0)) + 0.15;\n" +
" gl_FragColor = vec4(bw_color * lumen, color.a);\n" +
"}\n";
@@ -150,12 +153,17 @@ public class LomoishFilter extends Filter {
private void initParameters() {
if (mProgram !=null) {
- float centerX = (float) (0.5 * mWidth);
- float centerY = (float) (0.5 * mHeight);
- float center[] = {centerX, centerY};
- float max_dist = (float) Math.sqrt(centerX * centerX + centerY * centerY);
-
- mProgram.setHostValue("center", center);
+ float scale[] = new float[2];
+ if (mWidth > mHeight) {
+ scale[0] = 1f;
+ scale[1] = ((float) mHeight) / mWidth;
+ } else {
+ scale[0] = ((float) mWidth) / mHeight;
+ scale[1] = 1f;
+ }
+ float max_dist = ((float) Math.sqrt(scale[0] * scale[0] + scale[1] * scale[1])) * 0.5f;
+
+ mProgram.setHostValue("scale", scale);
mProgram.setHostValue("inv_max_dist", 1.0f / max_dist);
mProgram.setHostValue("stepsize", 1.0f / 255.0f);
diff --git a/media/mca/filterpacks/java/android/filterpacks/imageproc/VignetteFilter.java b/media/mca/filterpacks/java/android/filterpacks/imageproc/VignetteFilter.java
index 2d78fff..715fec6 100644
--- a/media/mca/filterpacks/java/android/filterpacks/imageproc/VignetteFilter.java
+++ b/media/mca/filterpacks/java/android/filterpacks/imageproc/VignetteFilter.java
@@ -51,11 +51,12 @@ public class VignetteFilter extends Filter {
"uniform float range;\n" +
"uniform float inv_max_dist;\n" +
"uniform float shade;\n" +
- "uniform vec2 center;\n" +
+ "uniform vec2 scale;\n" +
"varying vec2 v_texcoord;\n" +
"void main() {\n" +
" const float slope = 20.0;\n" +
- " float dist = distance(gl_FragCoord.xy, center);\n" +
+ " vec2 coord = v_texcoord - 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(tex_sampler_0, v_texcoord);\n" +
" gl_FragColor = vec4(color.rgb * lumen, color.a);\n" +
@@ -93,13 +94,17 @@ public class VignetteFilter extends Filter {
private void initParameters() {
if (mProgram != null) {
- float centerX = (float) (0.5 * mWidth);
- float centerY = (float) (0.5 * mHeight);
- float center[] = {centerX, centerY};
- float max_dist = (float) Math.sqrt(centerX * centerX + centerY * centerY);
-
- mProgram.setHostValue("center", center);
- mProgram.setHostValue("inv_max_dist", 1.0f / max_dist);
+ float scale[] = new float[2];
+ if (mWidth > mHeight) {
+ scale[0] = 1f;
+ scale[1] = ((float) mHeight) / mWidth;
+ } else {
+ scale[0] = ((float) mWidth) / mHeight;
+ scale[1] = 1f;
+ }
+ float max_dist = ((float) Math.sqrt(scale[0] * scale[0] + scale[1] * scale[1])) * 0.5f;
+ mProgram.setHostValue("scale", scale);
+ mProgram.setHostValue("inv_max_dist", 1f / max_dist);
mProgram.setHostValue("shade", mShade);
updateParameters();