loqusion / hyprshade

Hyprland shader configuration tool
MIT License
280 stars 7 forks source link

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

Closed id-ekaagr closed 6 months ago

id-ekaagr commented 10 months ago

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 commented 10 months ago

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 commented 9 months ago

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 commented 9 months ago

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 commented 9 months ago

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:

What this filter does:

Thanks loqusion.

loqusion commented 9 months ago

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 commented 9 months ago

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 commented 9 months ago

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.