-
Notifications
You must be signed in to change notification settings - Fork 110
Closed
Labels
Description
We have an accessibility requirement to magnify a portion of the screen for visual impaired users. I've started working on a magnifier shader, but GLSL + algebra is going to take me a while. I'd like for a magnifier shader to be part of the shaders included with Lightning. I've attached what I have so far.. I'm sure it can be made better + fancier by someone who knows what they are doing.
Screen.Recording.2021-01-06.at.12.27.43.PM.mov
import DefaultShader from 'wpe-lightning/src/renderer/webgl/shaders/DefaultShader';
export default class MagnifierShader extends DefaultShader {
constructor(context) {
super(context);
this._x = 0;
this._y = 0;
this._w = 0;
this._h = 0;
this._radius = 0;
this._magnification = 0.6;
}
get x() {
return this._x;
}
set x(v) {
this._x = v;
this.redraw();
}
get y() {
return this._y;
}
set y(v) {
this._y = v;
this.redraw();
}
get w() {
return this._w;
}
set w(v) {
this._w = v;
this.redraw();
}
get h() {
return this._h;
}
set h(v) {
this._h = v;
this.redraw();
}
set a(v) {
this._a = v;
this.redraw();
}
get a() {
return this._a;
}
get magnification() {
return this._magnification;
}
set magnification(v) {
this._magnification = v;
this.redraw();
}
get radius() {
return this._radius;
}
set radius(v) {
this._radius = v;
this.redraw();
}
setupUniforms(operation) {
super.setupUniforms(operation);
const owner = operation.shaderOwner;
const renderPrecision = this.ctx.stage.getRenderPrecision();
this._setUniform('x', this._x * renderPrecision, this.gl.uniform1f);
this._setUniform('y', this._y * renderPrecision, this.gl.uniform1f);
this._setUniform('w', this._w * renderPrecision, this.gl.uniform1f);
this._setUniform('h', this._h * renderPrecision, this.gl.uniform1f);
this._setUniform('magnification', this._magnification, this.gl.uniform1f);
this._setUniform('a', this._a, this.gl.uniform1f);
this._setUniform(
'radius',
(this._radius + 0.5) * renderPrecision,
this.gl.uniform1f
);
this._setUniform(
'resolution',
new Float32Array([
owner._w * renderPrecision,
owner._h * renderPrecision
]),
this.gl.uniform2fv
);
}
beforeDraw() {
this.gl.enable(this.gl.BLEND);
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
}
afterDraw() {
this.gl.disable(this.gl.BLEND);
}
useDefault() {
return this._x === 0 && this._y === 0 && this._w === 0 && this._h === 0;
}
}
MagnifierShader.vertexShaderSource = DefaultShader.vertexShaderSource;
MagnifierShader.fragmentShaderSource = `
#ifdef GL_ES
# ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
# else
precision lowp float;
# endif
#endif
varying vec2 vTextureCoord;
varying vec4 vColor;
uniform sampler2D uSampler;
uniform float x;
uniform float y;
uniform float w;
uniform float h;
uniform vec2 resolution;
uniform float radius;
uniform float magnification;
uniform float a;
float roundBox(vec2 p, vec2 b, float r) {
float d = length(max(abs(p)-b+r, 0.1))-r;
return smoothstep(1.0, 0.0, d);
}
void main(void) {
vec4 color = texture2D(uSampler, vTextureCoord);
vec2 pos = vTextureCoord.xy * resolution - vec2(x, y) - vec2(w, h) / 2.0;
vec2 size = vec2(w, h) / 2.0;
float b = roundBox(pos, size, radius);
vec2 pos2 = (vTextureCoord.xy * magnification * resolution + vec2(x, y) * magnification) / resolution;
gl_FragColor = mix(color, texture2D(uSampler, pos2), b);
}
`;