diff --git a/app/src/main/assets/shaders/demosaicp12b.glsl b/app/src/main/assets/shaders/demosaicp12b.glsl new file mode 100644 index 00000000..142a4381 --- /dev/null +++ b/app/src/main/assets/shaders/demosaicp12b.glsl @@ -0,0 +1,127 @@ +precision highp float; +precision mediump sampler2D; +uniform sampler2D RawBuffer; +uniform sampler2D GradBuffer; +#define QUAD 0 +#define demosw (1.0/10000.0) +#define EPS (0.01) +#define size1 (1.2) +#define MSIZE1 3 +#define KSIZE ((MSIZE1-1)/2) +#define GRADSIZE 1.5 +#define FUSEMIN 0.0 +#define FUSEMAX 1.0 +#define FUSESHIFT -0.1 +#define FUSEMPY 1.4 +#define NOISEO 0.0 +#define NOISES 0.0 +#define PI 3.1415926535897932384626433832795 +out float Output; + +// Helper function to get Bayer sample +float getBayerSample(ivec2 pos) { + return texelFetch(RawBuffer, pos, 0).r; +} + +float normpdf(in float x, in float sigma){return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma;} +void main() { + ivec2 xy = ivec2(gl_FragCoord.xy); + int fact1 = xy.x%2; + int fact2 = xy.y%2; + float outp = 0.0; + if(fact1+fact2 != 1){ + float outp = 0.0; + float weight = 0.0; + float green[4]; + green[0] = getBayerSample(ivec2(xy+ivec2(0, -1))) + (getBayerSample(xy) - getBayerSample(xy + ivec2(0,-2)))/2.0 + (getBayerSample(xy + ivec2(0,-3)) - 2.0 * getBayerSample(xy + ivec2(0,-1)) + getBayerSample(xy + ivec2(0,1)))/8.0; + green[1] = getBayerSample(ivec2(xy+ivec2(-1, 0))) + (getBayerSample(xy) - getBayerSample(xy + ivec2(-2,0)))/2.0 + (getBayerSample(xy + ivec2(-3,0)) - 2.0 * getBayerSample(xy + ivec2(-1,0)) + getBayerSample(xy + ivec2(1,0)))/8.0; + green[2] = getBayerSample(ivec2(xy+ivec2(1, 0))) + (getBayerSample(xy) - getBayerSample(xy + ivec2(2,0)))/2.0 + (getBayerSample(xy + ivec2(-1,0)) - 2.0 * getBayerSample(xy + ivec2(1,0)) + getBayerSample(xy + ivec2(3,0)))/8.0; + green[3] = getBayerSample(ivec2(xy+ivec2(0, 1))) + (getBayerSample(xy) - getBayerSample(xy + ivec2(0,2)))/2.0 + (getBayerSample(xy + ivec2(0,-1)) - 2.0 * getBayerSample(xy + ivec2(0,1)) + getBayerSample(xy + ivec2(0,3)))/8.0; + float grad[4]; + vec2 initialGrad = texelFetch(GradBuffer, ivec2(xy), 0).rg; + grad[0] = initialGrad.g*initialGrad.g; + grad[1] = initialGrad.r*initialGrad.r; + grad[2] = initialGrad.r*initialGrad.r; + grad[3] = initialGrad.g*initialGrad.g; + for (int i =1;i<=2;i++){ + if (i == 0) continue; + float t = texelFetch(GradBuffer, ivec2(xy+ivec2(0, -i)), 0).g; + grad[0] += t*t; + t = texelFetch(GradBuffer, ivec2(xy+ivec2(-i, 0)), 0).r; + grad[1] += t*t; + t = texelFetch(GradBuffer, ivec2(xy+ivec2(i, 0)), 0).r; + grad[2] += t*t; + t = texelFetch(GradBuffer, ivec2(xy+ivec2(0, i)), 0).g; + grad[3] += t*t; + } + grad[0] = 1.0/sqrt(grad[0]+demosw); + grad[1] = 1.0/sqrt(grad[1]+demosw); + grad[2] = 1.0/sqrt(grad[2]+demosw); + grad[3] = 1.0/sqrt(grad[3]+demosw); + + vec2 HV = vec2(demosw); + float weights = 0.00001; + for (int j =-2;j<=2;j++) + { + float k0 = normpdf(float(j), GRADSIZE); + for (int i =-2;i<=2;i++){ + if((i%2) + (j%2) != 1) continue; + float k = normpdf(float(i), GRADSIZE)*k0; + vec2 div = texelFetch(GradBuffer, ivec2(xy+ivec2(i, j)), 0).rg; + HV += div*k; + weights+=k; + } + } + float MIN = min(min(green[0],green[1]),min(green[2],green[3])); + float MAX = max(max(green[0],green[1]),max(green[2],green[3])); + float dmax = 1.0 - MAX; + float W; + if(dmax < MIN){ + W = dmax/MAX; + } else { + W = MIN/MAX; + } + float avr = (green[0]+green[1]+green[2]+green[3])/4.0; + //float N = sqrt(avr*NOISES + NOISEO)/5.0; + //W=W*W; + //W=sqrt(W); + //float badGR = (abs(HV.r-HV.g)*5.0)/((HV.r+HV.g)); + HV/=weights; + //if(abs(HV.r) > N || abs(HV.g) > N){ + //float angle = atan(dxy.y,dxy.x)+PI; + vec2 dxy2 = vec2((HV.x+HV.y)/2.0,(HV.y-HV.x)/2.0); + float avrg = (green[0]*grad[0]+green[1]*grad[1]+green[2]*grad[2]+green[3]*grad[3])/(grad[0]+grad[1]+grad[2]+grad[3]); + grad[0] = 1.0/sqrt(HV.x*HV.x+abs(green[0]-avrg)+demosw); + grad[1] = 1.0/sqrt(HV.y*HV.y+abs(green[1]-avrg)+demosw); + grad[2] = 1.0/sqrt(HV.y*HV.y+abs(green[2]-avrg)+demosw); + grad[3] = 1.0/sqrt(HV.x*HV.x+abs(green[3]-avrg)+demosw); + + //Output = (green[0]*grad[0] +green[1]*grad[1] + green[2]*grad[2]+ green[3]*grad[3])/(grad[0]+grad[1]+grad[2]+grad[3]); + float outp2 = 0.0; + + if (HV.y > HV.x){ + Output = (green[1]*grad[1] + green[2]*grad[2])/(grad[1]+grad[2]); + //Output = (green[1] + green[2])/(2.0); + } else { + Output = (green[0]*grad[0] + green[3]*grad[3])/(grad[0]+grad[3]); + //Output = (green[0] + green[3])/(2.0); + } + //Output = mix(outp2,Output,0.5 - 0.5*abs(HV.y-HV.x)); + /*} else { + Output = avr; + }*/ + + + W = mix(FUSEMIN,FUSEMAX,clamp((W+FUSESHIFT)*FUSEMPY,0.0,1.0)); + //Output = mix(Output,(green[0]*grad[0] + green[1]*grad[1]+ green[2]*grad[2] + green[3]*grad[3])/(grad[0]+grad[1]+grad[2]+grad[3]),W); + + + /*} else { + Output = green[0]*grad[0] + green[1]*grad[1]+ green[2]*grad[2] + green[3]*grad[3]; + Output/=grad[0]+grad[1]+grad[2]+grad[3]; + }*/ + } + else { + Output = float(texelFetch(RawBuffer, (xy), 0).x); + } +} diff --git a/app/src/main/assets/shaders/demosaicp12e.glsl b/app/src/main/assets/shaders/demosaicp12e.glsl new file mode 100644 index 00000000..d5adf4ba --- /dev/null +++ b/app/src/main/assets/shaders/demosaicp12e.glsl @@ -0,0 +1,134 @@ +precision highp float; +precision highp sampler2D; +uniform sampler2D bayerTexture; +#define alpha 3.75 +#define THRESHOLD 1.9 +#define L 3 +out vec3 Output; +uniform int yOffset; + +// Helper function to get Bayer sample +float getBayerSample(ivec2 pos) { + return texelFetch(bayerTexture, pos, 0).r; +} + +// Helper function to determine Bayer pattern at a given position +// 0: R, 1: G (at red row), 2: G (at blue row), 3: B +int getBayerPattern(ivec2 pos) { + int x = (pos.x) % 2; + int y = (pos.y) % 2; + return (y << 1) | x; +} + +float dxy(ivec2 pos, int direction) { + int pattern = getBayerPattern(pos); + float useGreen = (pattern == 1 || pattern == 2) ? 1.0 : -1.0; + if (direction == 0) { + return abs((4.0 * getBayerSample(pos) - 3.0 * getBayerSample(pos + ivec2(1,0)) - 3.0 * getBayerSample(pos + ivec2(-1,0)) + getBayerSample(pos + ivec2(-2,0)) + getBayerSample(pos + ivec2(2,0)))/6.0); + //return (2.0 * getBayerSample(pos) - getBayerSample(pos + ivec2(1,0)) - getBayerSample(pos + ivec2(-1,0)))/2.0; + } else { + return abs((4.0 * getBayerSample(pos) - 3.0 * getBayerSample(pos + ivec2(0,1)) - 3.0 * getBayerSample(pos + ivec2(0,-1)) + getBayerSample(pos + ivec2(0,-2)) + getBayerSample(pos + ivec2(0,2)))/6.0); + //return (2.0 * getBayerSample(pos) - getBayerSample(pos + ivec2(0,1)) - getBayerSample(pos + ivec2(0,-1)))/2.0; + } +} + +float dt(ivec2 pos, int direction) { + float c = dxy(pos, direction); + if (direction == 0) { + float c2 = dxy(pos + ivec2(2, 0), direction); + float c1 = dxy(pos + ivec2(1, 0), direction); + return (abs(c - c1) + abs(c1 - c2))/2.0; + } else { + float c2 = dxy(pos + ivec2(0, 2), direction); + float c1 = dxy(pos + ivec2(0, 1), direction); + return (abs(c - c1) + abs(c1 - c2))/2.0; + } +} + +float dxy2(ivec2 pos, int direction) { + float c = getBayerSample(pos); + float c1; + float c2; + float c3; + if (direction == 0){ + c1 = getBayerSample(pos + ivec2(2,0)); + c2 = getBayerSample(pos + ivec2(-1,0)); + c3 = getBayerSample(pos + ivec2(1,0)); + } else { + c1 = getBayerSample(pos + ivec2(0,2)); + c2 = getBayerSample(pos + ivec2(0,-1)); + c3 = getBayerSample(pos + ivec2(0,1)); + } + return (abs(c - c1) + abs(c2 - c3)) / 2.0 + alpha * dt(pos,direction); +} + +float IG(ivec2 pos, int direction) { + int pattern = getBayerPattern(pos); + float useGreen = (pattern == 1 || pattern == 2) ? -1.0 : 1.0; + float useInv = 1.0 - useGreen; + if (direction == 0) { + return 2.0 * dxy2(pos,0) + dxy2(pos + ivec2(0,-1),0) + dxy2(pos + ivec2(0,1),0); + } else { + return 2.0 * dxy2(pos,1) + dxy2(pos + ivec2(-1,0),1) + dxy2(pos + ivec2(1,0),1); + } +} + + +// Green plane interpolation +vec3 interpolateGreen(ivec2 pos) { + int pattern = getBayerPattern(pos); + if (pattern == 1 || pattern == 2) return vec3(getBayerSample(pos),0.0,0.0); // Already green + + float igE = IG(pos,1); + float igS = IG(pos,0); + float igW = IG(pos + ivec2(2,0),1); + float igN = IG(pos + ivec2(0,2),0); + + float wE = 1.0 / (igE + 0.0001); + float wS = 1.0 / (igS + 0.0001); + float wW = 1.0 / (igW + 0.0001); + float wN = 1.0 / (igN + 0.0001); + // Pass 1 + float gE = getBayerSample(pos + ivec2(0,1)) + (getBayerSample(pos) - getBayerSample(pos + ivec2(0,2)))/2.0 + (getBayerSample(pos + ivec2(0,-1)) - 2.0 * getBayerSample(pos + ivec2(0,1)) + getBayerSample(pos + ivec2(0,3)))/8.0; + float gW = getBayerSample(pos + ivec2(0,-1)) + (getBayerSample(pos) - getBayerSample(pos + ivec2(0,-2)))/2.0 + (getBayerSample(pos + ivec2(0,-3)) - 2.0 * getBayerSample(pos + ivec2(0,-1)) + getBayerSample(pos + ivec2(0,1)))/8.0; + float gN = getBayerSample(pos + ivec2(-1,0)) + (getBayerSample(pos) - getBayerSample(pos + ivec2(-2,0)))/2.0 + (getBayerSample(pos + ivec2(-3,0)) - 2.0 * getBayerSample(pos + ivec2(-1,0)) + getBayerSample(pos + ivec2(1,0)))/8.0; + float gS = getBayerSample(pos + ivec2(1,0)) + (getBayerSample(pos) - getBayerSample(pos + ivec2(2,0)))/2.0 + (getBayerSample(pos + ivec2(-1,0)) - 2.0 * getBayerSample(pos + ivec2(1,0)) + getBayerSample(pos + ivec2(3,0)))/8.0; + + float gh = (gE * wE + gW * wW)/(wE + wW + 0.0001); + float gv = (gN * wN + gS * wS)/(wN + wS + 0.0001); + float gd = (gE * wE + gW * wW + gN * wN + gS * wS)/(wE + wW + wN + wS + 0.0001); + + float dh = igE + igW; + float dv = igN + igS; + + float E = max(dh/dv, dv/dh); + + if (E < THRESHOLD) { + return vec3(-1.0, gh, gv); + } else { + if (dh > dv) { + return vec3(gv, gh, gv); + } else { + return vec3(gh, gh, gv); + } + } + /*if (dh > dv) { + return vec3(gv, gh, gv); + //return vec3(gv, gh, gv); + } else { + return vec3(gh, gh, gv); + //return vec3(gh, gh, gv); + }*/ + + return vec3(0.0); +} + + +void main() { + ivec2 pos = ivec2(gl_FragCoord.xy); + pos+=ivec2(0,yOffset); + + // Step 1: Green plane interpolation + vec3 initialGreen = interpolateGreen(pos); + Output = initialGreen; +} \ No newline at end of file diff --git a/app/src/main/assets/shaders/demosaicp12f.glsl b/app/src/main/assets/shaders/demosaicp12f.glsl new file mode 100644 index 00000000..a4dd7fa5 --- /dev/null +++ b/app/src/main/assets/shaders/demosaicp12f.glsl @@ -0,0 +1,224 @@ +precision highp float; +precision highp sampler2D; +uniform sampler2D bayerTexture; +uniform sampler2D greenTexture; +#define alpha 3.75 +#define THRESHOLD 1.9 +#define L 3 +out vec2 Output; +uniform int yOffset; + +// Helper function to get Bayer sample +float getBayerSample(ivec2 pos) { + return texelFetch(bayerTexture, pos, 0).r; +} + +// Helper function to determine Bayer pattern at a given position +// 0: R, 1: G (at red row), 2: G (at blue row), 3: B +int getBayerPattern(ivec2 pos) { + int x = (pos.x) % 2; + int y = (pos.y) % 2; + return (y << 1) | x; +} + +float dxy(ivec2 pos, int direction) { + int pattern = getBayerPattern(pos); + float useGreen = (pattern == 1 || pattern == 2) ? 1.0 : -1.0; + if (direction == 0) { + return abs((4.0 * getBayerSample(pos) - 3.0 * getBayerSample(pos + ivec2(1,0)) - 3.0 * getBayerSample(pos + ivec2(-1,0)) + getBayerSample(pos + ivec2(-2,0)) + getBayerSample(pos + ivec2(2,0)))/6.0); + //return (2.0 * getBayerSample(pos) - getBayerSample(pos + ivec2(1,0)) - getBayerSample(pos + ivec2(-1,0)))/2.0; + } else { + return abs((4.0 * getBayerSample(pos) - 3.0 * getBayerSample(pos + ivec2(0,1)) - 3.0 * getBayerSample(pos + ivec2(0,-1)) + getBayerSample(pos + ivec2(0,-2)) + getBayerSample(pos + ivec2(0,2)))/6.0); + //return (2.0 * getBayerSample(pos) - getBayerSample(pos + ivec2(0,1)) - getBayerSample(pos + ivec2(0,-1)))/2.0; + } +} + +float dt(ivec2 pos, int direction) { + float c = dxy(pos, direction); + if (direction == 0) { + float c2 = dxy(pos + ivec2(2, 0), direction); + float c1 = dxy(pos + ivec2(1, 0), direction); + return (abs(c - c1) + abs(c1 - c2))/2.0; + } else { + float c2 = dxy(pos + ivec2(0, 2), direction); + float c1 = dxy(pos + ivec2(0, 1), direction); + return (abs(c - c1) + abs(c1 - c2))/2.0; + } +} + +float dxy2(ivec2 pos, int direction) { + float c = getBayerSample(pos); + float c1; + float c2; + float c3; + if (direction == 0){ + c1 = getBayerSample(pos + ivec2(2,0)); + c2 = getBayerSample(pos + ivec2(-1,0)); + c3 = getBayerSample(pos + ivec2(1,0)); + } else { + c1 = getBayerSample(pos + ivec2(0,2)); + c2 = getBayerSample(pos + ivec2(0,-1)); + c3 = getBayerSample(pos + ivec2(0,1)); + } + return (abs(c - c1) + abs(c2 - c3)) / 2.0 + alpha * dt(pos,direction); +} + +float IG(ivec2 pos, int direction) { + int pattern = getBayerPattern(pos); + float useGreen = (pattern == 1 || pattern == 2) ? -1.0 : 1.0; + float useInv = 1.0 - useGreen; + if (direction == 0) { + return 2.0 * dxy2(pos,0) + dxy2(pos + ivec2(0,-1),0) + dxy2(pos + ivec2(0,1),0); + } else { + return 2.0 * dxy2(pos,1) + dxy2(pos + ivec2(-1,0),1) + dxy2(pos + ivec2(1,0),1); + } +} + + +// Green plane interpolation +vec3 interpolateGreen(ivec2 pos) { + return texelFetch(greenTexture, pos, 0).rgb; +} + +float ph(ivec2 pos) { + vec3 g = interpolateGreen(pos); + float c = getBayerSample(pos); + if (g[0] < 0.0) { + return g[1] - c; + } + return g[0] - c; +} + +float pv(ivec2 pos) { + vec3 g = interpolateGreen(pos); + float c = getBayerSample(pos); + if (g[0] < 0.0) { + return g[2] - c; + } + return g[0] - c; +} + +float pd(ivec2 pos) { + vec3 g = interpolateGreen(pos); + float c = getBayerSample(pos); + if (g[0] < 0.0) { + return (g[1]+g[2])/2.0 - c; + } + return g[0] - c; +} + +float gd(ivec2 pos) { + vec3 g = interpolateGreen(pos); + if (g[0] < 0.0) { + return (g[1]+g[2])/2.0; + } + return g[0]; +} + + +// Green plane enhancement +vec2 enhanceGreen(ivec2 pos) { + vec3 initialGreen = interpolateGreen(pos); + int pattern = getBayerPattern(pos); + float igE = IG(pos,1); + float igS = IG(pos,0); + float igW = IG(pos + ivec2(-2,0),1); + float igN = IG(pos + ivec2(0,-2),0); + + float wE = 1.0 / (igE + 0.0001); + float wS = 1.0 / (igS + 0.0001); + float wW = 1.0 / (igW + 0.0001); + float wN = 1.0 / (igN + 0.0001); + + float dh = igE + igW; + float dv = igN + igS; + float dir = 0.0; + if (dh > dv) { + dir = 1.0; + } else { + dir = 0.0; + } + if (pattern == 1 || pattern == 2 || initialGreen[0] > 0.0) return vec2(initialGreen[0], dir); // Already green + + // Pass 2 + vec3 D = vec3(0.0); + for (int dx = -L; dx <= L; dx++) { + D.x += abs(ph(pos) - ph(pos + ivec2(2*dx, 0))); + D.y += abs(pv(pos) - pv(pos + ivec2(0, 2*dx))); + D.z += abs(pd(pos) - pd(pos + ivec2(2*dx, 0))) + abs(pd(pos) - pd(pos + ivec2(0, 2*dx))); + } + D.z /= 2.0; + vec3 gs = vec3(initialGreen[1], initialGreen[2], (initialGreen[1]+initialGreen[2])/2.0); + dh = D.y; + dv = D.x; + if (D.x < D.y && D.x < D.z) { + initialGreen[0] = gs[0]; + dir = 1.0; + //g = gs[1]; + } else if (D.y < D.x && D.y < D.z) { + initialGreen[0] = gs[1]; + dir = 0.0; + //g = gs[0]; + } else { + initialGreen[0] = gs[2]; + dir = 0.5; + //g = gs[2]; + } + + return vec2(initialGreen[0], dir); +} + +// Red and Blue plane interpolation +/* +vec3 interpolateRedBlue(ivec2 pos, float green) { + int pattern = getBayerPattern(pos); + vec3 result; + result.g = green; + + float igH = computeIG(pos, 0); + float igV = computeIG(pos, 1); + + if (pattern == 0) { // Red center + result.r = getBayerSample(pos); + // Interpolate Blue + float b1 = green - (getBayerSample(pos + ivec2(-1, -1)) - getBayerSample(pos + ivec2(-1, -1))); + float b2 = green - (getBayerSample(pos + ivec2(1, -1)) - getBayerSample(pos + ivec2(1, -1))); + float b3 = green - (getBayerSample(pos + ivec2(-1, 1)) - getBayerSample(pos + ivec2(-1, 1))); + float b4 = green - (getBayerSample(pos + ivec2(1, 1)) - getBayerSample(pos + ivec2(1, 1))); + result.b = (b1 + b2 + b3 + b4) / 4.0; + } else if (pattern == 3) { // Blue center + result.b = getBayerSample(pos); + // Interpolate Red + float r1 = green - (getBayerSample(pos + ivec2(-1, -1)) - getBayerSample(pos + ivec2(-1, -1))); + float r2 = green - (getBayerSample(pos + ivec2(1, -1)) - getBayerSample(pos + ivec2(1, -1))); + float r3 = green - (getBayerSample(pos + ivec2(-1, 1)) - getBayerSample(pos + ivec2(-1, 1))); + float r4 = green - (getBayerSample(pos + ivec2(1, 1)) - getBayerSample(pos + ivec2(1, 1))); + result.r = (r1 + r2 + r3 + r4) / 4.0; + } else if (pattern == 1) { // Green in red row + // Interpolate Red + result.r = igH < igV ? (getBayerSample(pos + ivec2(-1, 0)) + getBayerSample(pos + ivec2(1, 0))) / 2.0 : + (getBayerSample(pos + ivec2(0, -1)) + getBayerSample(pos + ivec2(0, 1))) / 2.0; + // Interpolate Blue + result.b = (getBayerSample(pos + ivec2(-1, -1)) + getBayerSample(pos + ivec2(1, -1)) + + getBayerSample(pos + ivec2(-1, 1)) + getBayerSample(pos + ivec2(1, 1))) / 4.0; + } else { // Green in blue row + // Interpolate Blue + result.b = igH < igV ? (getBayerSample(pos + ivec2(-1, 0)) + getBayerSample(pos + ivec2(1, 0))) / 2.0 : + (getBayerSample(pos + ivec2(0, -1)) + getBayerSample(pos + ivec2(0, 1))) / 2.0; + // Interpolate Red + result.r = (getBayerSample(pos + ivec2(-1, -1)) + getBayerSample(pos + ivec2(1, -1)) + + getBayerSample(pos + ivec2(-1, 1)) + getBayerSample(pos + ivec2(1, 1))) / 4.0; + } + + return result; +}*/ + +void main() { + ivec2 pos = ivec2(gl_FragCoord.xy); + pos+=ivec2(0,yOffset); + // Step 2: Green plane enhancement + vec2 enhancedGreen = enhanceGreen(pos); + + // Step 3: Red and Blue plane interpolation + Output = enhancedGreen; +} \ No newline at end of file diff --git a/app/src/main/assets/shaders/demosaicp2e.glsl b/app/src/main/assets/shaders/demosaicp2e.glsl new file mode 100644 index 00000000..17302228 --- /dev/null +++ b/app/src/main/assets/shaders/demosaicp2e.glsl @@ -0,0 +1,212 @@ +precision highp float; +precision highp sampler2D; +uniform sampler2D RawBuffer; +uniform sampler2D GreenBuffer; +uniform int yOffset; +out vec3 Output; + + +#define alpha 3.75 +#define BETA 0.42 +#define THRESHOLD 1.9 +#define L 3 +//#define greenmin (0.04) +#define greenmin (0.01) +//#define greenmax (0.9) +#define greenmax (0.99) +#import interpolation + +int getBayerPattern(ivec2 pos) { + int x = pos.x % 2; + int y = pos.y % 2; + if (x == 0 && y == 0) return 0; // R G + if (x == 1 && y == 0) return 1; // G R + if (x == 0 && y == 1) return 2; // G B + return 3; // B G +} + +float getBayerSample(ivec2 pos) { + return float(texelFetch(RawBuffer, pos, 0).x); +} + +float gr(ivec2 pos){ + return float(texelFetch(GreenBuffer, pos, 0).x); +} + +float bayer(ivec2 pos){ + return float(texelFetch(RawBuffer, pos, 0).x); +} + +float dgr(ivec2 pos){ + return gr(pos) - bayer(pos); +} + + +float dxy(ivec2 pos, int direction) { + int pattern = getBayerPattern(pos); + float useGreen = (pattern == 1 || pattern == 2) ? 1.0 : -1.0; + if (direction == 0) { + return abs((4.0 * getBayerSample(pos) - 3.0 * getBayerSample(pos + ivec2(1,0)) - 3.0 * getBayerSample(pos + ivec2(-1,0)) + getBayerSample(pos + ivec2(-2,0)) + getBayerSample(pos + ivec2(2,0)))/6.0); + //return (2.0 * getBayerSample(pos) - getBayerSample(pos + ivec2(1,0)) - getBayerSample(pos + ivec2(-1,0)))/2.0; + } else { + return abs((4.0 * getBayerSample(pos) - 3.0 * getBayerSample(pos + ivec2(0,1)) - 3.0 * getBayerSample(pos + ivec2(0,-1)) + getBayerSample(pos + ivec2(0,-2)) + getBayerSample(pos + ivec2(0,2)))/6.0); + //return (2.0 * getBayerSample(pos) - getBayerSample(pos + ivec2(0,1)) - getBayerSample(pos + ivec2(0,-1)))/2.0; + } +} + +float dt(ivec2 pos, int direction) { + float c = dxy(pos, direction); + if (direction == 0) { + float c2 = dxy(pos + ivec2(2, 0), direction); + float c1 = dxy(pos + ivec2(1, 0), direction); + return (abs(c - c1) + abs(c1 - c2))/2.0; + } else { + float c2 = dxy(pos + ivec2(0, 2), direction); + float c1 = dxy(pos + ivec2(0, 1), direction); + return (abs(c - c1) + abs(c1 - c2))/2.0; + } +} + +float dxy2(ivec2 pos, int direction) { + float c = getBayerSample(pos); + float c1; + float c2; + float c3; + if (direction == 0){ + c1 = getBayerSample(pos + ivec2(2,0)); + c2 = getBayerSample(pos + ivec2(-1,0)); + c3 = getBayerSample(pos + ivec2(1,0)); + } else { + c1 = getBayerSample(pos + ivec2(0,2)); + c2 = getBayerSample(pos + ivec2(0,-1)); + c3 = getBayerSample(pos + ivec2(0,1)); + } + return (abs(c - c1) + abs(c2 - c3)) / 2.0 + alpha * dt(pos,direction); +} + +float IG(ivec2 pos, int direction) { + int pattern = getBayerPattern(pos); + float useGreen = (pattern == 1 || pattern == 2) ? -1.0 : 1.0; + float useInv = 1.0 - useGreen; + if (direction == 0) { + return 2.0 * dxy2(pos,0) + dxy2(pos + ivec2(0,-1),0) + dxy2(pos + ivec2(0,1),0); + } else { + return 2.0 * dxy2(pos,1) + dxy2(pos + ivec2(-1,0),1) + dxy2(pos + ivec2(1,0),1); + } +} + + +float interpolateColor(in ivec2 coords){ + bool usegreen = true; + float green[5]; + green[0] = float(texelFetch(GreenBuffer, (coords+ivec2(-1,-1)), 0).x); + green[1] = float(texelFetch(GreenBuffer, (coords+ivec2(1,-1)), 0).x); + green[2] = float(texelFetch(GreenBuffer, (coords+ivec2(-1,1)), 0).x); + green[3] = float(texelFetch(GreenBuffer, (coords+ivec2(1,1)), 0).x); + green[4] = float(texelFetch(GreenBuffer, (coords), 0).x); + for(int i = 0; i<5; i++)if(green[i] < greenmin || green[i] > greenmax) usegreen = false; + if(usegreen){ + float coeff[4]; + coeff[0] = float(texelFetch(RawBuffer, (coords+ivec2(-1,-1)), 0).x)/(green[0]); + coeff[1] = float(texelFetch(RawBuffer, (coords+ivec2(1,-1)), 0).x)/(green[1]); + coeff[2] = float(texelFetch(RawBuffer, (coords+ivec2(-1,1)), 0).x)/(green[2]); + coeff[3] = float(texelFetch(RawBuffer, (coords+ivec2(1,1)), 0).x)/(green[3]); + return (green[4]*(coeff[0]+coeff[1]+coeff[2]+coeff[3])/4.); + } else { + return ((float(texelFetch(RawBuffer, (coords+ivec2(-1,-1)), 0).x)+float(texelFetch(RawBuffer, (coords+ivec2(1,-1)), 0).x) + +float(texelFetch(RawBuffer, (coords+ivec2(-1,1)), 0).x)+float(texelFetch(RawBuffer, (coords+ivec2(1,1)), 0).x))/(4.)); + } +} +float interpolateColorx(in ivec2 coords){ + bool usegreen = true; + float green[3]; + green[0] = float(texelFetch(GreenBuffer, (coords+ivec2(-1,0)), 0).x); + green[1] = float(texelFetch(GreenBuffer, (coords+ivec2(0,0)), 0).x); + green[2] = float(texelFetch(GreenBuffer, (coords+ivec2(1,0)), 0).x); + for(int i = 0; i<3; i++)if(green[i] < greenmin || green[i] > greenmax) usegreen = false; + if(usegreen){ + float coeff[2]; + coeff[0] = float(texelFetch(RawBuffer, (coords+ivec2(-1,0)), 0).x)/(green[0]); + coeff[1] = float(texelFetch(RawBuffer, (coords+ivec2(1,0)), 0).x)/(green[2]); + return (green[1]*(coeff[0]+coeff[1])/2.); + } else { + return ((float(texelFetch(RawBuffer, (coords+ivec2(-1,0)), 0).x)+float(texelFetch(RawBuffer, (coords+ivec2(1,0)), 0).x))/(2.)); + } +} +float interpolateColory(in ivec2 coords){ + bool usegreen = true; + float green[3]; + green[0] = float(texelFetch(GreenBuffer, (coords+ivec2(0,-1)), 0).x); + green[1] = float(texelFetch(GreenBuffer, (coords+ivec2(0,0)), 0).x); + green[2] = float(texelFetch(GreenBuffer, (coords+ivec2(0,1)), 0).x); + for(int i = 0; i<3; i++)if(green[i] < greenmin || green[i] > greenmax) usegreen = false; + if(usegreen){ + float coeff[2]; + coeff[0] = float(texelFetch(RawBuffer, (coords+ivec2(0,-1)), 0).x)/(green[0]); + coeff[1] = float(texelFetch(RawBuffer, (coords+ivec2(0,1)), 0).x)/(green[2]); + return (green[1]*(coeff[0]+coeff[1])/2.); + } else { + return ((float(texelFetch(RawBuffer, (coords+ivec2(0,-1)), 0).x)+float(texelFetch(RawBuffer, (coords+ivec2(0,1)), 0).x))/(2.)); + } +} + +float dl(ivec2 pos){ + return getBayerSample(pos) - gr(pos); +} + +float estimateD(ivec2 pos){ + float igE = IG(pos, 1); + float igS = IG(pos, 0); + float igW = IG(pos + ivec2(-2, 0), 1); + float igN = IG(pos + ivec2(0, -2), 0); + + float wE = 1.0 / (igE + 0.0001); + float wS = 1.0 / (igS + 0.0001); + float wW = 1.0 / (igW + 0.0001); + float wN = 1.0 / (igN + 0.0001); + + float dir = float(texelFetch(GreenBuffer, pos, 0).y); + float dte = 0.0; + if (dir < 0.5){ + dte = (wE * dl(pos + ivec2(0, 2)) + wW * dl(pos + ivec2(0, -2)))/(wE + wW); + } else { + if (dir > 0.5){ + dte = (wS * dl(pos + ivec2(2, 0)) + wN * dl(pos + ivec2(-2, 0)))/(wS + wN); + } else { + dte = (wE * dl(pos + ivec2(0, 2)) + wW * dl(pos + ivec2(0, -2)) + wS * dl(pos + ivec2(2, 0)) + wN * dl(pos + ivec2(-2, 0)))/(wE + wW + wS + wN); + } + } + return dte; +} + +void main() { + ivec2 xy = ivec2(gl_FragCoord.xy); + int fact1 = xy.x%2; + int fact2 = xy.y%2; + xy+=ivec2(0,yOffset); + //float dtc = mix(estimateD(xy), dl(xy), BETA); + if(fact1 ==0 && fact2 == 0) {//rggb + Output.g = texelFetch(GreenBuffer, (xy), 0).x; + Output.r = float(texelFetch(RawBuffer, (xy), 0).x); + Output.b = interpolateColor(xy); + //Output.g = getBayerSample(xy) - dtc; + //Output.b = gr(xy) + dtc; + } else + if(fact1 ==1 && fact2 == 0) {//grbg + Output.g = texelFetch(GreenBuffer, (xy), 0).x; + Output.r = interpolateColorx(xy); + Output.b = interpolateColory(xy); + } else + if(fact1 ==0 && fact2 == 1) {//gbrg + Output.g = texelFetch(GreenBuffer, (xy), 0).x; + Output.b = interpolateColorx(xy); + Output.r = interpolateColory(xy); + + } else {//bggr + Output.g = texelFetch(GreenBuffer, (xy), 0).x; + Output.b = float(texelFetch(RawBuffer, (xy), 0).x); + Output.r = interpolateColor(xy); + //Output.g = getBayerSample(xy) - dtc; + } + Output = clamp(Output,0.0,1.0); +} \ No newline at end of file diff --git a/app/src/main/assets/shaders/exposebayer2.glsl b/app/src/main/assets/shaders/exposebayer2.glsl index 917236c9..128ac09f 100644 --- a/app/src/main/assets/shaders/exposebayer2.glsl +++ b/app/src/main/assets/shaders/exposebayer2.glsl @@ -66,11 +66,11 @@ void main() { inp.g = texelFetch(InputBuffer, xyCenter+ivec2(1,0), 0).r; inp.b = texelFetch(InputBuffer, xyCenter+ivec2(0,1), 0).r; inp.a = texelFetch(InputBuffer, xyCenter+ivec2(1,1), 0).r; + //vec4 gains = textureBicubicHardware(GainMap, vec2(xyCenter)/vec2(textureSize(InputBuffer, 0))); + //inp *= (gains.r + gains.g + gains.b + gains.a) / 4.0; inp = clamp(inp,vec4(0.0001),vec3(NEUTRALPOINT).rggb)/vec3(NEUTRALPOINT).rggb; - vec4 gains = textureBicubicHardware(GainMap, vec2(xyCenter)/vec2(textureSize(InputBuffer, 0))); - gains.rgb = vec3(gains.r,(gains.g+gains.b)/2.0,gains.a); - inp *= dot(gains.rgb,vec3(1.0/3.0)); + vec3 v3 = brIn2(inp,STRLOW); float br = luminocity(v3); diff --git a/app/src/main/assets/shaders/initial.glsl b/app/src/main/assets/shaders/initial.glsl index 543bbded..e388da50 100644 --- a/app/src/main/assets/shaders/initial.glsl +++ b/app/src/main/assets/shaders/initial.glsl @@ -331,7 +331,9 @@ void main() { float blurCorrected = 0.f; for(int i = -1; i<=2;i++){ for(int j = -1; j<=2;j++){ + //vec4 gains = textureBicubicHardware(GainMap, vec2(xy+ivec2(i,j))/vec2(textureSize(InputBuffer, 0))); float v = dot(texelFetch(InputBuffer, xy+ivec2(i,j), 0).rgb, vec3(1.f)); + //v *= (gains.r+gains.g+gains.b+gains.a)/4.0; blurInitial += v; blurCorrected += v*getGain(vec2(ivec2(i,j))); } diff --git a/app/src/main/java/com/particlesdevs/photoncamera/processing/opengl/postpipeline/Demosaic2.java b/app/src/main/java/com/particlesdevs/photoncamera/processing/opengl/postpipeline/Demosaic2.java index 55d62f13..c987a02e 100644 --- a/app/src/main/java/com/particlesdevs/photoncamera/processing/opengl/postpipeline/Demosaic2.java +++ b/app/src/main/java/com/particlesdevs/photoncamera/processing/opengl/postpipeline/Demosaic2.java @@ -48,7 +48,7 @@ public void Run() { glProg.setDefine("NOISES",basePipeline.noiseS); glProg.setDefine("NOISEO",basePipeline.noiseO); startT(); - glProg.useAssetProgram("demosaicp12"); + glProg.useAssetProgram("demosaicp12b"); glProg.setTexture("RawBuffer",previousNode.WorkingTexture); glProg.setTexture("GradBuffer",basePipeline.main3); if(basePipeline.mSettings.cfaPattern == -2) glProg.setDefine("QUAD","1"); diff --git a/app/src/main/java/com/particlesdevs/photoncamera/processing/opengl/postpipeline/Demosaic3.java b/app/src/main/java/com/particlesdevs/photoncamera/processing/opengl/postpipeline/Demosaic3.java new file mode 100644 index 00000000..23e7a79a --- /dev/null +++ b/app/src/main/java/com/particlesdevs/photoncamera/processing/opengl/postpipeline/Demosaic3.java @@ -0,0 +1,49 @@ +package com.particlesdevs.photoncamera.processing.opengl.postpipeline; + +import com.particlesdevs.photoncamera.processing.opengl.GLTexture; +import com.particlesdevs.photoncamera.processing.opengl.nodes.Node; + +public class Demosaic3 extends Node { + public Demosaic3() { + super("", "Demosaic"); + } + + @Override + public void Compile() {} + float gradSize = 1.5f; + float fuseMin = 0.f; + float fuseMax = 1.f; + float fuseShift = -0.5f; + float fuseMpy = 6.0f; + @Override + public void Run() { + gradSize = getTuning("GradSize",gradSize); + fuseMin = getTuning("FuseMin",fuseMin); + fuseMax = getTuning("FuseMax",fuseMax); + fuseShift = getTuning("FuseShift",fuseShift); + fuseMpy = getTuning("FuseMpy",fuseMpy); + GLTexture glTexture; + glTexture = previousNode.WorkingTexture; + //Gradients + GLTexture outp; + + //Colour channels + startT(); + glProg.useAssetProgram("demosaicp12e"); + glProg.setTexture("bayerTexture",glTexture); + WorkingTexture = basePipeline.main3; + glProg.drawBlocks(WorkingTexture); + glProg.useAssetProgram("demosaicp12f"); + glProg.setTexture("bayerTexture", glTexture); + glProg.setTexture("greenTexture", WorkingTexture); + outp = basePipeline.getMain(); + glProg.drawBlocks(outp); + //glProg.drawBlocks(WorkingTexture); + glProg.useAssetProgram("demosaicp2"); + glProg.setTexture("RawBuffer", glTexture); + glProg.setTexture("GreenBuffer", outp); + glProg.drawBlocks(WorkingTexture); + glProg.close(); + endT("Demosaic2"); + } +} diff --git a/app/version.properties b/app/version.properties index 0c806bd1..f157c56c 100644 --- a/app/version.properties +++ b/app/version.properties @@ -1,2 +1,2 @@ -#Thu Jul 11 23:16:51 KGT 2024 -VERSION_BUILD=17060 +#Sat Jul 13 01:36:21 KGT 2024 +VERSION_BUILD=17094