[RFC,v3,5/7] libcamera: shaders: Add LSC support
diff mbox series

Message ID 20260424200255.356798-6-mzamazal@redhat.com
State New
Headers show
Series
  • LSC for SoftISP simple pipeline
Related show

Commit Message

Milan Zamazal April 24, 2026, 8:02 p.m. UTC
From: Xander Pronk <xander.c.pronk@gmail.com>

Lens shading correction should be applied after black level
subtraction (in order to make the computations with meaningful values)
and before white balance (especially before white balance stats are
computed).

Note that lens shading correction depends on temperature, which depends
on white balance, so there is a chicken-egg problem.  Currently, we
determine white balance and temperature from the preceding frame.

Co-developed-by: Rick ten Wolde <rick_libcamera@wolde.info>
Signed-off-by: Rick ten Wolde <rick_libcamera@wolde.info>
Signed-off-by: Xander Pronk <xander.c.pronk@gmail.com>
Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
---
 src/libcamera/shaders/bayer_1x_packed.frag | 9 +++++++++
 src/libcamera/shaders/bayer_unpacked.frag  | 9 +++++++++
 2 files changed, 18 insertions(+)

Comments

Laurent Pinchart April 24, 2026, 9:12 p.m. UTC | #1
On Fri, Apr 24, 2026 at 10:02:51PM +0200, Milan Zamazal wrote:
> From: Xander Pronk <xander.c.pronk@gmail.com>
> 
> Lens shading correction should be applied after black level
> subtraction (in order to make the computations with meaningful values)
> and before white balance (especially before white balance stats are
> computed).
> 
> Note that lens shading correction depends on temperature, which depends
> on white balance, so there is a chicken-egg problem.  Currently, we
> determine white balance and temperature from the preceding frame.

Why is there a chicken-egg problem specific to LSC ?

> Co-developed-by: Rick ten Wolde <rick_libcamera@wolde.info>
> Signed-off-by: Rick ten Wolde <rick_libcamera@wolde.info>
> Signed-off-by: Xander Pronk <xander.c.pronk@gmail.com>
> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
> ---
>  src/libcamera/shaders/bayer_1x_packed.frag | 9 +++++++++
>  src/libcamera/shaders/bayer_unpacked.frag  | 9 +++++++++
>  2 files changed, 18 insertions(+)
> 
> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag
> index 23747f78a..dfa787c22 100644
> --- a/src/libcamera/shaders/bayer_1x_packed.frag
> +++ b/src/libcamera/shaders/bayer_1x_packed.frag
> @@ -70,6 +70,10 @@ uniform vec3 blacklevel;
>  uniform float gamma;
>  uniform float contrastExp;
>  
> +#if defined(APPLY_LSC)
> +uniform sampler2D lsc_tex;
> +#endif
> +
>  float apply_contrast(float value)
>  {
>  	// Apply simple S-curve
> @@ -227,6 +231,11 @@ void main(void)
>  
>  	rgb = rgb - blacklevel;
>  
> +	#if defined(APPLY_LSC)

Let's align that to the left column.

> +        /* Transformation of the lsc_tex value range: 0.0..1.0 -> 1.0..3.0 */

Mix of tabs and spaces for indentation. Is there a good linter for GLSL
that we could use in CI ?

I assume this is meant to obtain gains from x1.0 to x4.0. The range
seems fine, but the comment would benefit from explaining it more
clearly. Maybe something like

	/*
	 * Map lsc_tex RGB values from the [0.0, 1.0] range to [x1.0, x4.0]
	 * gains.
	 */

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +	rgb = rgb + rgb * 3.0 * texture2D(lsc_tex, textureOut).rgb;
> +	#endif
> +
>  	/*
>  	 *   CCM is a 3x3 in the format
>  	 *
> diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag
> index 1b85196ae..e10d55c0a 100644
> --- a/src/libcamera/shaders/bayer_unpacked.frag
> +++ b/src/libcamera/shaders/bayer_unpacked.frag
> @@ -29,6 +29,10 @@ uniform vec3            blacklevel;
>  uniform float           gamma;
>  uniform float           contrastExp;
>  
> +#if defined(APPLY_LSC)
> +uniform sampler2D lsc_tex;
> +#endif
> +
>  float apply_contrast(float value)
>  {
>      // Apply simple S-curve
> @@ -130,6 +134,11 @@ void main(void) {
>  
>      rgb = rgb - blacklevel;
>  
> +    #if defined(APPLY_LSC)
> +    /* Transformation of the lsc_tex value range: 0.0..1.0 -> 1.0..3.0 */
> +    rgb = rgb + rgb * 3.0 * texture2D(lsc_tex, center.xy).rgb;
> +    #endif
> +
>      /*
>       *   CCM is a 3x3 in the format
>       *

Patch
diff mbox series

diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag
index 23747f78a..dfa787c22 100644
--- a/src/libcamera/shaders/bayer_1x_packed.frag
+++ b/src/libcamera/shaders/bayer_1x_packed.frag
@@ -70,6 +70,10 @@  uniform vec3 blacklevel;
 uniform float gamma;
 uniform float contrastExp;
 
+#if defined(APPLY_LSC)
+uniform sampler2D lsc_tex;
+#endif
+
 float apply_contrast(float value)
 {
 	// Apply simple S-curve
@@ -227,6 +231,11 @@  void main(void)
 
 	rgb = rgb - blacklevel;
 
+	#if defined(APPLY_LSC)
+        /* Transformation of the lsc_tex value range: 0.0..1.0 -> 1.0..3.0 */
+	rgb = rgb + rgb * 3.0 * texture2D(lsc_tex, textureOut).rgb;
+	#endif
+
 	/*
 	 *   CCM is a 3x3 in the format
 	 *
diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag
index 1b85196ae..e10d55c0a 100644
--- a/src/libcamera/shaders/bayer_unpacked.frag
+++ b/src/libcamera/shaders/bayer_unpacked.frag
@@ -29,6 +29,10 @@  uniform vec3            blacklevel;
 uniform float           gamma;
 uniform float           contrastExp;
 
+#if defined(APPLY_LSC)
+uniform sampler2D lsc_tex;
+#endif
+
 float apply_contrast(float value)
 {
     // Apply simple S-curve
@@ -130,6 +134,11 @@  void main(void) {
 
     rgb = rgb - blacklevel;
 
+    #if defined(APPLY_LSC)
+    /* Transformation of the lsc_tex value range: 0.0..1.0 -> 1.0..3.0 */
+    rgb = rgb + rgb * 3.0 * texture2D(lsc_tex, center.xy).rgb;
+    #endif
+
     /*
      *   CCM is a 3x3 in the format
      *