[libcamera-devel] [RFC PATCH v5 9/9] qcam: viewfinder_gl: bayer_8.frag: compute the coordinates manually

Andrey Konovalov andrey.konovalov at linaro.org
Tue Jun 22 15:46:52 CEST 2021


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 at linaro.org>
---
 src/qcam/assets/shader/bayer_8.frag | 38 ++++++++++++++++++++++++++---
 src/qcam/viewfinder_gl.cpp          |  4 ---
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/src/qcam/assets/shader/bayer_8.frag b/src/qcam/assets/shader/bayer_8.frag
index 4ece44ab..be23913b 100644
--- a/src/qcam/assets/shader/bayer_8.frag
+++ b/src/qcam/assets/shader/bayer_8.frag
@@ -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;
 
diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
index e7c8620c..a5b1bfbe 100644
--- a/src/qcam/viewfinder_gl.cpp
+++ b/src/qcam/viewfinder_gl.cpp
@@ -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;
-- 
2.25.1



More information about the libcamera-devel mailing list