| Message ID | 20260821125958.95928-5-mzamazal@redhat.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
2026. 08. 21. 14:59 keltezéssel, Milan Zamazal írta: > 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 is > computed from the preceding, rather than current, frame (this is due to > how white balance is currently computed). > > The shaders are compiled on initialisation, while lens shading > correction can be enabled or disabled dynamically, using the > corresponding control. The whole correction in the shader is wrapped by > a conditional macro to be able to disable it and all the related > overheads if Lsc algorithm is not enabled at all. > > If Lsc algorithm is enabled, the correction is always applied, whether > the given control is enabled or not. If it is not, 1.0 multipliers are > expected to be provided. This is because lens shading correction is > supposed to be rarely switched off using the runtime control when Lsc > algorithm is enabled, e.g. only for demoing or debugging purposes. > We prefer accepting the performance penalty of applying a no-op > correction in such cases rather than disturbing GPU computation in the > regular flow by introducing a runtime `if'. > > lsc_tex texture contains 8-bit UQ<2, 6> quantized data as provided by > the IPA algorithm. It is converted to float in the shader by > multiplying it by 4.0. > > 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> > Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> > --- > 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 0b641a5f3..765fc8e88 100644 > --- a/src/libcamera/shaders/bayer_1x_packed.frag > +++ b/src/libcamera/shaders/bayer_1x_packed.frag > @@ -71,6 +71,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 > @@ -232,6 +236,11 @@ void main(void) > */ > rgb = (rgb - blacklevel) / (1.0 - blacklevel); > > +#if defined(APPLY_LSC) > + /* Multiple by 4.0 for UQ<2, 6> -> float conversion */ > + rgb = rgb * (texture2D(lsc_tex, textureOut).rgb * 4.0); > +#endif > + > /* Apply AWB gains, and saturate each channel at sensor range */ > rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0)); > > diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag > index 10c5e941b..be2f89dd0 100644 > --- a/src/libcamera/shaders/bayer_unpacked.frag > +++ b/src/libcamera/shaders/bayer_unpacked.frag > @@ -30,6 +30,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 > @@ -135,6 +139,11 @@ void main(void) { > */ > rgb = (rgb - blacklevel) / (1.0 - blacklevel); > > +#if defined(APPLY_LSC) > + /* Multiple by 4.0 for UQ<2, 6> -> float conversion */ I'd expand it, noting that: texture2D(...) = original * 2^6 (quantization) * 1/2^8 (texture byte to float) -> original = texture2D(...) / 2^6 * 2^8 = texture2D(...) * 2^2 because it was not immediately obvious to me. Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > + rgb = rgb * (texture2D(lsc_tex, center.xy).rgb * 4.0); > +#endif > + > /* Apply AWB gains, and saturate each channel at sensor range */ > rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0)); >
diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag index 0b641a5f3..765fc8e88 100644 --- a/src/libcamera/shaders/bayer_1x_packed.frag +++ b/src/libcamera/shaders/bayer_1x_packed.frag @@ -71,6 +71,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 @@ -232,6 +236,11 @@ void main(void) */ rgb = (rgb - blacklevel) / (1.0 - blacklevel); +#if defined(APPLY_LSC) + /* Multiple by 4.0 for UQ<2, 6> -> float conversion */ + rgb = rgb * (texture2D(lsc_tex, textureOut).rgb * 4.0); +#endif + /* Apply AWB gains, and saturate each channel at sensor range */ rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0)); diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag index 10c5e941b..be2f89dd0 100644 --- a/src/libcamera/shaders/bayer_unpacked.frag +++ b/src/libcamera/shaders/bayer_unpacked.frag @@ -30,6 +30,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 @@ -135,6 +139,11 @@ void main(void) { */ rgb = (rgb - blacklevel) / (1.0 - blacklevel); +#if defined(APPLY_LSC) + /* Multiple by 4.0 for UQ<2, 6> -> float conversion */ + rgb = rgb * (texture2D(lsc_tex, center.xy).rgb * 4.0); +#endif + /* Apply AWB gains, and saturate each channel at sensor range */ rgb = clamp(rgb * awb, vec3(0.0), vec3(1.0));