Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace blue-light-filter's code. #12

Closed
id-ekaagr opened this issue Dec 9, 2023 · 7 comments
Closed

Replace blue-light-filter's code. #12

id-ekaagr opened this issue Dec 9, 2023 · 7 comments
Labels
enhancement New feature or request

Comments

@id-ekaagr
Copy link

Please replace the code below with blue-light-shader.glsl. This one is properly formatted.

// from https://github.com/hyprwm/Hyprland/issues/1140#issuecomment-1335128437

precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D tex;

const float temperatureStrength = 1.0;
const float temperature = 4800.0;

#define WithQuickAndDirtyLuminancePreservation
const float LuminancePreservationFactor = 1.0;

// function from https://www.shadertoy.com/view/4sc3D7
vec3 colorTemperatureToRGB(const in float temperature) {
  // values from: http://blenderartists.org/forum/showthread.php?270332-OSL-Goodness&p=2268693&viewfull=1#post2268693
  mat3 m = (temperature <= 6500.0) ?
    mat3 (
      vec3 (0.0, -2902.1955373783176   , -8257.7997278925690   ),
      vec3 (0.0,  1669.5803561666639   ,  2575.2827530017594   ),
      vec3 (1.0,     1.3302673723350029,     1.8993753891711275)
    ) :
    mat3 (
      vec3 ( 1745.0425298314172    ,  1216.6168361476490    , -8257.7997278925690   ),
      vec3 (-2666.3474220535695    , -2173.1012343082230    ,  2575.2827530017594   ),
      vec3 (    0.55995389139931482,     0.70381203140554553,     1.8993753891711275)
    );
  return mix (
    clamp (
      vec3 (
        m[0] / (
          vec3 (
            clamp (
              temperature,
              1000.0,
              40000.0
            )
          ) + m[1]
        ) + m[2]
      ),
      vec3(0.0),
      vec3(1.0)
    ),
    vec3(1.0),
    smoothstep(
      1000.0,
      0.0,
      temperature
    )
  );
}

void main() {
  vec4 pixColor = texture2D (
    tex,
    v_texcoord
  );

  // RGB
  vec3 color = vec3 (
    pixColor[0],
    pixColor[1],
    pixColor[2]
  );

  #ifdef WithQuickAndDirtyLuminancePreservation
  color *= mix (
    1.0,
    dot (
      color,
      vec3 (
        0.2126,
        0.7152,
        0.0722
      )
    ) / max (
      dot (
        color,
        vec3 (
          0.2126,
          0.7152,
          0.0722
        )
      ),
      1e-5
    ),
    LuminancePreservationFactor
  );
  #endif

  color = mix (
    color,
    color * colorTemperatureToRGB (
      temperature
    ),
    temperatureStrength
  );

  vec4 outCol = vec4 (
    color,
    pixColor[3]
  );

  gl_FragColor = outCol;
}
@loqusion
Copy link
Owner

I get this when I run clang-format:

// from https://github.com/hyprwm/Hyprland/issues/1140#issuecomment-1335128437

precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D tex;

const float temperature = 2600.0;
const float temperatureStrength = 1.0;

#define WithQuickAndDirtyLuminancePreservation
const float LuminancePreservationFactor = 1.0;

// function from https://www.shadertoy.com/view/4sc3D7
// valid from 1000 to 40000 K (and additionally 0 for pure full white)
vec3 colorTemperatureToRGB(const in float temperature) {
  // values from:
  // http://blenderartists.org/forum/showthread.php?270332-OSL-Goodness&p=2268693&viewfull=1#post2268693
  mat3 m = (temperature <= 6500.0)
               ? mat3(vec3(0.0, -2902.1955373783176, -8257.7997278925690),
                      vec3(0.0, 1669.5803561666639, 2575.2827530017594),
                      vec3(1.0, 1.3302673723350029, 1.8993753891711275))
               : mat3(vec3(1745.0425298314172, 1216.6168361476490,
                           -8257.7997278925690),
                      vec3(-2666.3474220535695, -2173.1012343082230,
                           2575.2827530017594),
                      vec3(0.55995389139931482, 0.70381203140554553,
                           1.8993753891711275));
  return mix(
      clamp(vec3(m[0] / (vec3(clamp(temperature, 1000.0, 40000.0)) + m[1]) +
                 m[2]),
            vec3(0.0), vec3(1.0)),
      vec3(1.0), smoothstep(1000.0, 0.0, temperature));
}

void main() {
  vec4 pixColor = texture2D(tex, v_texcoord);

  // RGB
  vec3 color = vec3(pixColor[0], pixColor[1], pixColor[2]);

#ifdef WithQuickAndDirtyLuminancePreservation
  color *= mix(1.0,
               dot(color, vec3(0.2126, 0.7152, 0.0722)) /
                   max(dot(color, vec3(0.2126, 0.7152, 0.0722)), 1e-5),
               LuminancePreservationFactor);
#endif

  color = mix(color, color * colorTemperatureToRGB(temperature),
              temperatureStrength);

  vec4 outCol = vec4(color, pixColor[3]);

  gl_FragColor = outCol;
}

What is the source/rationale behind your formatting?

@id-ekaagr
Copy link
Author

id-ekaagr commented Dec 14, 2023

Manually formatted the code for making it more readable.

This issue can safely be closed.

PS: Let me know what you think of this shader config. :)

// link: https://github.com/hyprwm/Hyprland/issues/1140#issuecomment-1614863627
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D tex;

const float X = 2.0;
const float R = X * X;
const float G = R * R;
const float B = G * G;
const float VIB_VIBRANCE = 1.0 / (R + B + G);
const vec3 VIB_RGB_BALANCE = vec3(
  R,
  G,
  B
);

const vec3 VIB_coeffVibrance = VIB_RGB_BALANCE * -VIB_VIBRANCE;

void main() {
  vec4 pixColor = texture2D(tex, v_texcoord);
  vec3 color = vec3 (
    pixColor[0],
    pixColor[1],
    pixColor[2]
  );

  vec3 VIB_coefLuma = vec3(
    R / (R + B + G),
    G / (R + B + G),
    B / (R + B + G)
  ) * X;

  float luma = dot(VIB_coefLuma, color);

  float max_color = max(color[0], max(color[1], color[2]));
  float min_color = min(color[0], min(color[1], color[2]));

  float color_saturation = max_color - min_color;

  vec3 p_col = vec3(vec3(vec3(vec3(sign(VIB_coeffVibrance) * color_saturation) - 1.0) * VIB_coeffVibrance) + 1.0);

  pixColor[0] = mix(luma, color[0], p_col[0]);
  pixColor[1] = mix(luma, color[1], p_col[1]);
  pixColor[2] = mix(luma, color[2], p_col[2]);

  gl_FragColor = pixColor;
}

It looked good for saving people's eyes from strain (keeping vibrancy), so I felt the need to share. Thanks for this amazing utility.

@loqusion
Copy link
Owner

Is that supposed to be vibrance or blue-light-filter?

This is what it looks like on my system:

image

vibrance:

image

blue-light-filter:

image

@id-ekaagr
Copy link
Author

id-ekaagr commented Dec 15, 2023

We can better call it a highlight-filter.

It's desirable by people who use light-colour-themes in their IDE's like VSCodium.

What are the drawbacks with blue-light-filter:

  • I use yellow colour for highlighting instance of clicked variable or selected text, stuff in yellow colour looks pretty dull.
  • Blue is a colour which is already high in contrast to white, but bad for the eyes.

What this filter does:

  • Removes blue light almost completely still doesn't compromise on contrast.
  • Yellow's look like they have been highlighted by a real pen on top of the screen, this makes finding things on screen very very easy. Red's are also significantly highlighted as red is the colour used for highlighting errors.
  • Saves eyes for working for longer duration, even the lowest amount of brightness on this filter will feel like enough bright.

Thanks loqusion.

@loqusion
Copy link
Owner

Just to clarify, does highlight-filter serve a similar purpose to blue-light-filter? Or are there situations where a user might want to switch between highlight-filter and blue-light-filter (e.g. based on what's displayed on the screen)? I'm wondering if this should be implemented as a blue-light-filter variant that is customizable in hyprshade.toml, or if it should be added as a separate highlight-filter.glsl.

@id-ekaagr
Copy link
Author

blue-light-filter is very scientific, highlight-filter is a filter for particular use case, it's also very aggressive on blue colour. So highlight-filter should be kept in a separate category initially. Once highlight-filter is tested enough it should become a variant of blue-light-filter, someday.

@id-ekaagr
Copy link
Author

id-ekaagr commented Dec 15, 2023

Here's the latest code for the filter:

// link: https://github.com/hyprwm/Hyprland/issues/1140#issuecomment-1614863627
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D tex;

const float X = 1.0;

const float N = 1.0 + X;
const float R = N * N;
const float G = R * R;
const float B = G * G;
const float S = R + G + B;
const float VIB_VIBRANCE = 1.0 / S;
const vec3 VIB_RGB_BALANCE = vec3(
  R,
  G,
  B
);

const vec3 VIB_coeffVibrance = VIB_RGB_BALANCE * -VIB_VIBRANCE;

void main() {
  vec4 pixColor = texture2D(tex, v_texcoord);
  vec3 color = vec3(pixColor[0], pixColor[1], pixColor[2]);

  vec3 VIB_coefLuma = vec3(R / S, G / S, B / S) * R;

  float luma = dot(VIB_coefLuma, color);

  float max_color = max(color[0], max(color[1], color[2]));
  float min_color = min(color[0], min(color[1], color[2]));

  float color_saturation = max_color - min_color;

  vec3 p_col = vec3(vec3(vec3(vec3(sign(VIB_coeffVibrance) * color_saturation) - 1.0) * VIB_coeffVibrance) + 1.0);

  pixColor[0] = mix(luma, color[0], p_col[0]);
  pixColor[1] = mix(luma, color[1], p_col[1]);
  pixColor[2] = mix(luma, color[2], p_col[2]);

  gl_FragColor = pixColor;
}

variable X stands for Intensity. Ideally X should be anything between 0.0 to 1.0.

@loqusion loqusion added the enhancement New feature or request label Jan 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants