[libcamera-devel,RFC,v5,9/9] qcam: viewfinder_gl: bayer_8.frag: compute the coordinates manually
diff mbox series

Message ID 20210622134652.1279260-10-andrey.konovalov@linaro.org
State Superseded
Headers show
Series
  • qcam: viewfinder_gl: add RAW8, RAW10P and RAW12P formats
Related show

Commit Message

Andrey Konovalov June 22, 2021, 1:46 p.m. UTC
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(-)

Patch
diff mbox series

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;