@@ -10,21 +10,51 @@ This paper appears in issue Volume 13, Number 4.
---------------------------------------------------------
Copyright (c) 2008, Morgan McGuire. All rights reserved.
-Modified by Linaro Ltd to integrate it into libcamera.
+
+Modified by Linaro Ltd to integrate it into libcamera, and to
+fix the artifacts due to pixel coordinates interpolation.
Copyright (C) 2021, Linaro
*/
//Pixel Shader
+varying vec2 textureOut;
+
+uniform vec2 tex_size; /* The texture size in pixels */
+uniform vec2 tex_step;
+
+/** Pixel position of the first red pixel in the */
+/** Bayer pattern. [{0,1}, {0, 1}]*/
+uniform vec2 tex_bayer_first_red;
+
/** Monochrome RGBA or GL_LUMINANCE Bayer encoded texture.*/
uniform sampler2D tex_y;
-varying vec4 center;
-varying vec4 yCoord;
-varying vec4 xCoord;
void main(void) {
#define fetch(x, y) texture2D(tex_y, vec2(x, y)).r
+ /** .xy = Pixel being sampled in the fragment shader on the range [0, 1]
+ .zw = ...on the range [0, sourceSize], offset by firstRed */
+ vec4 center;
+
+ /** center.x + (-2/w, -1/w, 1/w, 2/w); These are the x-positions */
+ /** of the adjacent pixels.*/
+ vec4 xCoord;
+
+ /** center.y + (-2/h, -1/h, 1/h, 2/h); These are the y-positions */
+ /** of the adjacent pixels.*/
+ vec4 yCoord;
+
+ /* Align the center coordinates to the nearest pixel */
+ center.zw = floor(textureOut * tex_size);
+ center.xy = center.zw * tex_step;
+ center.zw += tex_bayer_first_red;
+
+ xCoord = center.x + vec4(-2.0 * tex_step.x,
+ -tex_step.x, tex_step.x, 2.0 * tex_step.x);
+ yCoord = center.y + vec4(-2.0 * tex_step.y,
+ -tex_step.y, tex_step.y, 2.0 * tex_step.y);
+
float C = texture2D(tex_y, center.xy).r; // ( 0, 0)
const vec4 kC = vec4( 4.0, 6.0, 5.0, 5.0) / 8.0;
@@ -231,28 +231,24 @@ bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format)
case libcamera::formats::SBGGR8:
firstRed_.setX(1.0);
firstRed_.setY(1.0);
- vertexShaderFile_ = ":bayer_8.vert";
fragmentShaderFile_ = ":bayer_8.frag";
textureMinMagFilters_ = GL_NEAREST;
break;
case libcamera::formats::SGBRG8:
firstRed_.setX(0.0);
firstRed_.setY(1.0);
- vertexShaderFile_ = ":bayer_8.vert";
fragmentShaderFile_ = ":bayer_8.frag";
textureMinMagFilters_ = GL_NEAREST;
break;
case libcamera::formats::SGRBG8:
firstRed_.setX(1.0);
firstRed_.setY(0.0);
- vertexShaderFile_ = ":bayer_8.vert";
fragmentShaderFile_ = ":bayer_8.frag";
textureMinMagFilters_ = GL_NEAREST;
break;
case libcamera::formats::SRGGB8:
firstRed_.setX(0.0);
firstRed_.setY(0.0);
- vertexShaderFile_ = ":bayer_8.vert";
fragmentShaderFile_ = ":bayer_8.frag";
textureMinMagFilters_ = GL_NEAREST;
break;
Use the identity vertex shader, and compute the coordinates in the fragment shader without using the hardware interpolator. The texture coordinates passed to the fragment shader are ajusted to point to the nearest pixel in the image. This prevents artifacts when the image is scaled from the frame resolution to the window size. Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> --- src/qcam/assets/shader/bayer_8.frag | 38 ++++++++++++++++++++++++++--- src/qcam/viewfinder_gl.cpp | 4 --- 2 files changed, 34 insertions(+), 8 deletions(-)