Shortcuts you invent, rules you write, gestures you own - all still just data

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-25 01:51:59 -04:00
parent f9e5d3f470
commit 06c53d6c21
48 changed files with 4749 additions and 140 deletions
+28
View File
@@ -0,0 +1,28 @@
// Deuteranopia -- green-blind.
//
// Panama's accessibility color filters. Selected by the `colorFilter`
// preference; hypr/looks.lua maps the enum to this path at config time and
// services/SystemSettings.qml does the same live.
//
// Same family of matrices as protanopia.frag, weighted for the missing green
// cone instead of the red one. See that file for why this is a correction
// rather than a simulation, and for the column-major note.
#version 300 es
precision mediump float;
in vec2 v_texcoord;
layout(location = 0) out vec4 fragColor;
uniform sampler2D tex;
const mat3 deuteranopia = mat3(
0.625, 0.700, 0.000,
0.375, 0.300, 0.300,
0.000, 0.000, 0.700
);
void main() {
vec4 pixColor = texture(tex, v_texcoord);
fragColor = vec4(clamp(deuteranopia * pixColor.rgb, 0.0, 1.0), pixColor.a);
}
+28
View File
@@ -0,0 +1,28 @@
// Grayscale.
//
// Panama's accessibility color filters. Selected by the `colorFilter`
// preference; hypr/looks.lua maps the enum to this path at config time and
// services/SystemSettings.qml does the same live.
//
// Hyprland runs one fragment shader over the finished frame, so this covers
// every window, the shell, video and the cursor alike.
//
// Rec. 709 luminance weights -- the same ones an SVG <feColorMatrix
// type="saturate" values="0"> uses. A flat average would make reds and blues
// far too bright and greens far too dark, because the eye does not weigh the
// channels equally.
#version 300 es
precision mediump float;
in vec2 v_texcoord;
layout(location = 0) out vec4 fragColor;
uniform sampler2D tex;
void main() {
vec4 pixColor = texture(tex, v_texcoord);
float luminance = dot(pixColor.rgb, vec3(0.2126, 0.7152, 0.0722));
fragColor = vec4(vec3(luminance), pixColor.a);
}
+33
View File
@@ -0,0 +1,33 @@
// Protanopia -- red-blind.
//
// Panama's accessibility color filters. Selected by the `colorFilter`
// preference; hypr/looks.lua maps the enum to this path at config time and
// services/SystemSettings.qml does the same live.
//
// The matrix is the feColorMatrix set the mock uses, which is the widely
// carried HCIRN-derived one: it redistributes the red channel into the two the
// eye can still separate, so a red/green pair that was one colour becomes two
// distinguishable ones. It is a CORRECTION, not a simulation -- the point is to
// make the screen readable, not to show what protanopia looks like.
//
// Row-major here, column-major to GLSL: mat3 takes its arguments column by
// column, so the transpose below is the matrix as written in the SVG.
#version 300 es
precision mediump float;
in vec2 v_texcoord;
layout(location = 0) out vec4 fragColor;
uniform sampler2D tex;
const mat3 protanopia = mat3(
0.567, 0.558, 0.000,
0.433, 0.442, 0.242,
0.000, 0.000, 0.758
);
void main() {
vec4 pixColor = texture(tex, v_texcoord);
fragColor = vec4(clamp(protanopia * pixColor.rgb, 0.0, 1.0), pixColor.a);
}
+28
View File
@@ -0,0 +1,28 @@
// Tritanopia -- blue-blind.
//
// Panama's accessibility color filters. Selected by the `colorFilter`
// preference; hypr/looks.lua maps the enum to this path at config time and
// services/SystemSettings.qml does the same live.
//
// Same family of matrices as protanopia.frag, weighted for the missing blue
// cone. See that file for why this is a correction rather than a simulation,
// and for the column-major note.
#version 300 es
precision mediump float;
in vec2 v_texcoord;
layout(location = 0) out vec4 fragColor;
uniform sampler2D tex;
const mat3 tritanopia = mat3(
0.950, 0.000, 0.000,
0.050, 0.433, 0.475,
0.000, 0.567, 0.525
);
void main() {
vec4 pixColor = texture(tex, v_texcoord);
fragColor = vec4(clamp(tritanopia * pixColor.rgb, 0.0, 1.0), pixColor.a);
}