[client] egl: added colorblind support (egl:cbMode=0/1/2/3)

Based on http://www.daltonize.org/search/label/Daltonize

0 = Off
1 = Protanope
2 = Deuteranope
3 = Tritanope
This commit is contained in:
Geoffrey McRae 2020-11-09 06:59:54 +11:00
parent ed95f8863d
commit dd7e0ea8c6
5 changed files with 103 additions and 2 deletions

View File

@ -20,6 +20,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "cursor.h" #include "cursor.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/locking.h" #include "common/locking.h"
#include "common/option.h"
#include "texture.h" #include "texture.h"
#include "shader.h" #include "shader.h"
@ -47,6 +48,7 @@ struct EGL_Cursor
// cursor state // cursor state
bool visible; bool visible;
float x, y, w, h; float x, y, w, h;
int cbMode;
// textures // textures
struct EGL_Texture * texture; struct EGL_Texture * texture;
@ -59,6 +61,7 @@ struct EGL_Cursor
// uniforms // uniforms
GLuint uMousePos; GLuint uMousePos;
GLuint uMousePosMono; GLuint uMousePosMono;
GLuint uCBMode;
// model // model
struct EGL_Model * model; struct EGL_Model * model;
@ -118,8 +121,10 @@ bool egl_cursor_init(EGL_Cursor ** cursor)
return false; return false;
} }
(*cursor)->uMousePos = egl_shader_get_uniform_location((*cursor)->shader , "mouse"); (*cursor)->uMousePos = egl_shader_get_uniform_location((*cursor)->shader , "mouse" );
(*cursor)->uMousePosMono = egl_shader_get_uniform_location((*cursor)->shaderMono, "mouse"); (*cursor)->uCBMode = egl_shader_get_uniform_location((*cursor)->shader , "cbMode");
(*cursor)->uMousePosMono = egl_shader_get_uniform_location((*cursor)->shaderMono, "mouse" );
if (!egl_model_init(&(*cursor)->model)) if (!egl_model_init(&(*cursor)->model))
{ {
@ -128,6 +133,9 @@ bool egl_cursor_init(EGL_Cursor ** cursor)
} }
egl_model_set_default((*cursor)->model); egl_model_set_default((*cursor)->model);
(*cursor)->cbMode = option_get_int("egl", "cbMode");
return true; return true;
} }
@ -255,6 +263,7 @@ void egl_cursor_render(EGL_Cursor * cursor)
{ {
egl_shader_use(cursor->shader); egl_shader_use(cursor->shader);
glUniform4f(cursor->uMousePos, cursor->x, cursor->y, cursor->w, cursor->h / 2); glUniform4f(cursor->uMousePos, cursor->x, cursor->y, cursor->w, cursor->h / 2);
glUniform1i(cursor->uCBMode , cursor->cbMode);
glBlendFunc(GL_ZERO, GL_SRC_COLOR); glBlendFunc(GL_ZERO, GL_SRC_COLOR);
egl_model_set_texture(cursor->model, cursor->texture); egl_model_set_texture(cursor->model, cursor->texture);
egl_model_render(cursor->model); egl_model_render(cursor->model);
@ -271,6 +280,7 @@ void egl_cursor_render(EGL_Cursor * cursor)
{ {
egl_shader_use(cursor->shader); egl_shader_use(cursor->shader);
glUniform4f(cursor->uMousePos, cursor->x, cursor->y, cursor->w, cursor->h); glUniform4f(cursor->uMousePos, cursor->x, cursor->y, cursor->w, cursor->h);
glUniform1i(cursor->uCBMode , cursor->cbMode);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
egl_model_render(cursor->model); egl_model_render(cursor->model);
break; break;

View File

@ -43,6 +43,7 @@ struct DesktopShader
GLint uDesktopSize; GLint uDesktopSize;
GLint uNearest; GLint uNearest;
GLint uNV, uNVGain; GLint uNV, uNVGain;
GLint uCBMode;
}; };
struct EGL_Desktop struct EGL_Desktop
@ -64,6 +65,9 @@ struct EGL_Desktop
KeybindHandle kbNV; KeybindHandle kbNV;
int nvMax; int nvMax;
int nvGain; int nvGain;
// colorblind mode
int cbMode;
}; };
// forwards // forwards
@ -90,6 +94,7 @@ static bool egl_init_desktop_shader(
shader->uNearest = egl_shader_get_uniform_location(shader->shader, "nearest" ); shader->uNearest = egl_shader_get_uniform_location(shader->shader, "nearest" );
shader->uNV = egl_shader_get_uniform_location(shader->shader, "nv" ); shader->uNV = egl_shader_get_uniform_location(shader->shader, "nv" );
shader->uNVGain = egl_shader_get_uniform_location(shader->shader, "nvGain" ); shader->uNVGain = egl_shader_get_uniform_location(shader->shader, "nvGain" );
shader->uCBMode = egl_shader_get_uniform_location(shader->shader, "cbMode" );
return true; return true;
} }
@ -143,6 +148,7 @@ bool egl_desktop_init(EGL_Desktop ** desktop, EGLDisplay * display)
(*desktop)->nvMax = option_get_int("egl", "nvGainMax"); (*desktop)->nvMax = option_get_int("egl", "nvGainMax");
(*desktop)->nvGain = option_get_int("egl", "nvGain" ); (*desktop)->nvGain = option_get_int("egl", "nvGain" );
(*desktop)->cbMode = option_get_int("egl", "cbMode" );
return true; return true;
} }
@ -272,6 +278,7 @@ bool egl_desktop_render(EGL_Desktop * desktop, const float x, const float y, con
else else
glUniform1i(shader->uNV, 0); glUniform1i(shader->uNV, 0);
glUniform1i(shader->uCBMode, desktop->cbMode);
egl_model_render(desktop->model); egl_model_render(desktop->model);
return true; return true;
} }

View File

@ -134,6 +134,13 @@ static struct Option egl_options[] =
.type = OPTION_TYPE_INT, .type = OPTION_TYPE_INT,
.value.x_int = 0 .value.x_int = 0
}, },
{
.module = "egl",
.name = "cbMode",
.description = "Colorblind Mode (0 = Off, 1 = Protanope, 2 = Deuteranope, 3 = Tritanope)",
.type = OPTION_TYPE_INT,
.value.x_int = 0
},
{0} {0}
}; };

View File

@ -5,7 +5,46 @@ out highp vec4 color;
uniform sampler2D sampler1; uniform sampler2D sampler1;
uniform int cbMode;
void main() void main()
{ {
color = texture(sampler1, uv); color = texture(sampler1, uv);
if (cbMode > 0)
{
highp float L = (17.8824000 * color.r) + (43.516100 * color.g) + (4.11935 * color.b);
highp float M = (03.4556500 * color.r) + (27.155400 * color.g) + (3.86714 * color.b);
highp float S = (00.0299566 * color.r) + (00.184309 * color.g) + (1.46709 * color.b);
highp float l, m, s;
if (cbMode == 1) // Protanope
{
l = 0.0f * L + 2.02344f * M + -2.52581f * S;
m = 0.0f * L + 1.0f * M + 0.0f * S;
s = 0.0f * L + 0.0f * M + 1.0f * S;
}
else if (cbMode == 2) // Deuteranope
{
l = 1.000000 * L + 0.0f * M + 0.00000 * S;
m = 0.494207 * L + 0.0f * M + 1.24827 * S;
s = 0.000000 * L + 0.0f * M + 1.00000 * S;
}
else if (cbMode == 3) // Tritanope
{
l = 1.000000 * L + 0.000000 * M + 0.0 * S;
m = 0.000000 * L + 1.000000 * M + 0.0 * S;
s = -0.395913 * L + 0.801109 * M + 0.0 * S;
}
highp vec4 error;
error.r = ( 0.080944447900 * l) + (-0.13050440900 * m) + ( 0.116721066 * s);
error.g = (-0.010248533500 * l) + ( 0.05401932660 * m) + (-0.113614708 * s);
error.b = (-0.000365296938 * l) + (-0.00412161469 * m) + ( 0.693511405 * s);
error.a = 0.0;
error = color - error;
color.g += (error.r * 0.7) + (error.g * 1.0);
color.b += (error.r * 0.7) + (error.b * 1.0);
}
} }

View File

@ -10,6 +10,7 @@ uniform highp vec2 size;
uniform int nv; uniform int nv;
uniform highp float nvGain; uniform highp float nvGain;
uniform int cbMode;
void main() void main()
{ {
@ -18,6 +19,43 @@ void main()
else else
color = texelFetch(sampler1, ivec2(uv * size), 0); color = texelFetch(sampler1, ivec2(uv * size), 0);
if (cbMode > 0)
{
highp float L = (17.8824000 * color.r) + (43.516100 * color.g) + (4.11935 * color.b);
highp float M = (03.4556500 * color.r) + (27.155400 * color.g) + (3.86714 * color.b);
highp float S = (00.0299566 * color.r) + (00.184309 * color.g) + (1.46709 * color.b);
highp float l, m, s;
if (cbMode == 1) // Protanope
{
l = 0.0f * L + 2.02344f * M + -2.52581f * S;
m = 0.0f * L + 1.0f * M + 0.0f * S;
s = 0.0f * L + 0.0f * M + 1.0f * S;
}
else if (cbMode == 2) // Deuteranope
{
l = 1.000000 * L + 0.0f * M + 0.00000 * S;
m = 0.494207 * L + 0.0f * M + 1.24827 * S;
s = 0.000000 * L + 0.0f * M + 1.00000 * S;
}
else if (cbMode == 3) // Tritanope
{
l = 1.000000 * L + 0.000000 * M + 0.0 * S;
m = 0.000000 * L + 1.000000 * M + 0.0 * S;
s = -0.395913 * L + 0.801109 * M + 0.0 * S;
}
highp vec4 error;
error.r = ( 0.080944447900 * l) + (-0.13050440900 * m) + ( 0.116721066 * s);
error.g = (-0.010248533500 * l) + ( 0.05401932660 * m) + (-0.113614708 * s);
error.b = (-0.000365296938 * l) + (-0.00412161469 * m) + ( 0.693511405 * s);
error.a = 0.0;
error = color - error;
color.g += (error.r * 0.7) + (error.g * 1.0);
color.b += (error.r * 0.7) + (error.b * 1.0);
}
if (nv == 1) if (nv == 1)
{ {
highp float lumi = 1.0 - (0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b); highp float lumi = 1.0 - (0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b);