diff --git a/egui_glium/CHANGELOG.md b/egui_glium/CHANGELOG.md index e1cbab0f3..ccc562516 100644 --- a/egui_glium/CHANGELOG.md +++ b/egui_glium/CHANGELOG.md @@ -7,6 +7,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased +* Added GLSL 1.2 shaders (now `egui` works well on old hardware which supports OpenGL 2.1 only like Raspberry Pi 1 and Zero) +* Added GLSL ES 1.0 and 3.0 shaders (by reusing from webgl backend) + ## 0.9.0 - 2021-02-07 diff --git a/egui_glium/src/painter.rs b/egui_glium/src/painter.rs index 729f070e4..897451d87 100644 --- a/egui_glium/src/painter.rs +++ b/egui_glium/src/painter.rs @@ -8,6 +8,7 @@ use { glium::{ implement_vertex, index::PrimitiveType, + program, texture::{self, srgb_texture2d::SrgbTexture2d}, uniform, uniforms::{MagnifySamplerFilter, SamplerWrapFunction}, @@ -15,53 +16,6 @@ use { }, }; -const VERTEX_SHADER_SOURCE: &str = r#" - #version 140 - uniform vec2 u_screen_size; - in vec2 a_pos; - in vec4 a_srgba; // 0-255 sRGB - in vec2 a_tc; - out vec4 v_rgba; - out vec2 v_tc; - - // 0-1 linear from 0-255 sRGB - vec3 linear_from_srgb(vec3 srgb) { - bvec3 cutoff = lessThan(srgb, vec3(10.31475)); - vec3 lower = srgb / vec3(3294.6); - vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); - return mix(higher, lower, cutoff); - } - - vec4 linear_from_srgba(vec4 srgba) { - return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); - } - - void main() { - gl_Position = vec4( - 2.0 * a_pos.x / u_screen_size.x - 1.0, - 1.0 - 2.0 * a_pos.y / u_screen_size.y, - 0.0, - 1.0); - // egui encodes vertex colors in gamma spaces, so we must decode the colors here: - v_rgba = linear_from_srgba(a_srgba); - v_tc = a_tc; - } -"#; - -const FRAGMENT_SHADER_SOURCE: &str = r#" - #version 140 - uniform sampler2D u_sampler; - in vec4 v_rgba; - in vec2 v_tc; - out vec4 f_color; - - void main() { - // The texture sampler is sRGB aware, and glium already expects linear rgba output - // so no need for any sRGB conversions here: - f_color = v_rgba * texture(u_sampler, v_tc); - } -"#; - pub struct Painter { program: glium::Program, egui_texture: Option, @@ -83,9 +37,26 @@ struct UserTexture { impl Painter { pub fn new(facade: &dyn glium::backend::Facade) -> Painter { - let program = - glium::Program::from_source(facade, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE, None) - .expect("Failed to compile shader"); + let program = program! { + facade, + 120 => { + vertex: include_str!("shader/vertex_120.glsl"), + fragment: include_str!("shader/fragment_120.glsl"), + }, + 140 => { + vertex: include_str!("shader/vertex_140.glsl"), + fragment: include_str!("shader/fragment_140.glsl"), + }, + 100 es => { + vertex: include_str!("shader/vertex_100es.glsl"), + fragment: include_str!("shader/fragment_100es.glsl"), + }, + 300 es => { + vertex: include_str!("shader/vertex_300es.glsl"), + fragment: include_str!("shader/fragment_300es.glsl"), + }, + } + .expect("Failed to compile shader"); Painter { program, diff --git a/egui_glium/src/shader/fragment_100es.glsl b/egui_glium/src/shader/fragment_100es.glsl new file mode 100644 index 000000000..3ca63b536 --- /dev/null +++ b/egui_glium/src/shader/fragment_100es.glsl @@ -0,0 +1,45 @@ +#version 100 es + +precision mediump float; +uniform sampler2D u_sampler; +varying vec4 v_rgba; +varying vec2 v_tc; + +// 0-255 sRGB from 0-1 linear +vec3 srgb_from_linear(vec3 rgb) { + bvec3 cutoff = lessThan(rgb, vec3(0.0031308)); + vec3 lower = rgb * vec3(3294.6); + vec3 higher = vec3(269.025) * pow(rgb, vec3(1.0 / 2.4)) - vec3(14.025); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 srgba_from_linear(vec4 rgba) { + return vec4(srgb_from_linear(rgba.rgb), 255.0 * rgba.a); +} + +// 0-1 linear from 0-255 sRGB +vec3 linear_from_srgb(vec3 srgb) { + bvec3 cutoff = lessThan(srgb, vec3(10.31475)); + vec3 lower = srgb / vec3(3294.6); + vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 linear_from_srgba(vec4 srgba) { + return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); +} + +void main() { + // We must decode the colors, since WebGL doesn't come with sRGBA textures: + vec4 texture_rgba = linear_from_srgba(texture2D(u_sampler, v_tc) * 255.0); + + /// Multiply vertex color with texture color (in linear space). + gl_FragColor = v_rgba * texture_rgba; + + // We must gamma-encode again since WebGL doesn't support linear blending in the framebuffer. + gl_FragColor = srgba_from_linear(v_rgba * texture_rgba) / 255.0; + + // WebGL doesn't support linear blending in the framebuffer, + // so we apply this hack to at least get a bit closer to the desired blending: + gl_FragColor.a = pow(gl_FragColor.a, 1.6); // Empiric nonsense +} diff --git a/egui_glium/src/shader/fragment_120.glsl b/egui_glium/src/shader/fragment_120.glsl new file mode 100644 index 000000000..f7e8e3dc5 --- /dev/null +++ b/egui_glium/src/shader/fragment_120.glsl @@ -0,0 +1,11 @@ +#version 120 + +uniform sampler2D u_sampler; +varying vec4 v_rgba; +varying vec2 v_tc; + +void main() { + // The texture sampler is sRGB aware, and glium already expects linear rgba output + // so no need for any sRGB conversions here: + gl_FragColor = v_rgba * texture2D(u_sampler, v_tc); +} diff --git a/egui_glium/src/shader/fragment_140.glsl b/egui_glium/src/shader/fragment_140.glsl new file mode 100644 index 000000000..cad0bac10 --- /dev/null +++ b/egui_glium/src/shader/fragment_140.glsl @@ -0,0 +1,12 @@ +#version 140 + +uniform sampler2D u_sampler; +in vec4 v_rgba; +in vec2 v_tc; +out vec4 f_color; + +void main() { + // The texture sampler is sRGB aware, and glium already expects linear rgba output + // so no need for any sRGB conversions here: + f_color = v_rgba * texture(u_sampler, v_tc); +} diff --git a/egui_glium/src/shader/fragment_300es.glsl b/egui_glium/src/shader/fragment_300es.glsl new file mode 100644 index 000000000..65b37c9be --- /dev/null +++ b/egui_glium/src/shader/fragment_300es.glsl @@ -0,0 +1,33 @@ +#version 300 es + +precision mediump float; +uniform sampler2D u_sampler; +varying vec4 v_rgba; +varying vec2 v_tc; + +// 0-255 sRGB from 0-1 linear +vec3 srgb_from_linear(vec3 rgb) { + bvec3 cutoff = lessThan(rgb, vec3(0.0031308)); + vec3 lower = rgb * vec3(3294.6); + vec3 higher = vec3(269.025) * pow(rgb, vec3(1.0 / 2.4)) - vec3(14.025); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 srgba_from_linear(vec4 rgba) { + return vec4(srgb_from_linear(rgba.rgb), 255.0 * rgba.a); +} + +void main() { + // The texture is set up with `SRGB8_ALPHA8`, so no need to decode here! + vec4 texture_rgba = texture2D(u_sampler, v_tc); + + /// Multiply vertex color with texture color (in linear space). + gl_FragColor = v_rgba * texture_rgba; + + // We must gamma-encode again since WebGL doesn't support linear blending in the framebuffer. + gl_FragColor = srgba_from_linear(v_rgba * texture_rgba) / 255.0; + + // WebGL doesn't support linear blending in the framebuffer, + // so we apply this hack to at least get a bit closer to the desired blending: + gl_FragColor.a = pow(gl_FragColor.a, 1.6); // Empiric nonsense +} diff --git a/egui_glium/src/shader/vertex_100es.glsl b/egui_glium/src/shader/vertex_100es.glsl new file mode 100644 index 000000000..d7982452d --- /dev/null +++ b/egui_glium/src/shader/vertex_100es.glsl @@ -0,0 +1,32 @@ +#version 100 es + +precision mediump float; +uniform vec2 u_screen_size; +attribute vec2 a_pos; +attribute vec2 a_tc; +attribute vec4 a_srgba; +varying vec4 v_rgba; +varying vec2 v_tc; + +// 0-1 linear from 0-255 sRGB +vec3 linear_from_srgb(vec3 srgb) { + bvec3 cutoff = lessThan(srgb, vec3(10.31475)); + vec3 lower = srgb / vec3(3294.6); + vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 linear_from_srgba(vec4 srgba) { + return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); +} + +void main() { + gl_Position = vec4( + 2.0 * a_pos.x / u_screen_size.x - 1.0, + 1.0 - 2.0 * a_pos.y / u_screen_size.y, + 0.0, + 1.0); + // egui encodes vertex colors in gamma spaces, so we must decode the colors here: + v_rgba = linear_from_srgba(a_srgba); + v_tc = a_tc; +} diff --git a/egui_glium/src/shader/vertex_120.glsl b/egui_glium/src/shader/vertex_120.glsl new file mode 100644 index 000000000..8f419314c --- /dev/null +++ b/egui_glium/src/shader/vertex_120.glsl @@ -0,0 +1,31 @@ +#version 120 + +uniform vec2 u_screen_size; +attribute vec2 a_pos; +attribute vec4 a_srgba; // 0-255 sRGB +attribute vec2 a_tc; +varying vec4 v_rgba; +varying vec2 v_tc; + +// 0-1 linear from 0-255 sRGB +vec3 linear_from_srgb(vec3 srgb) { + bvec3 cutoff = lessThan(srgb, vec3(10.31475)); + vec3 lower = srgb / vec3(3294.6); + vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 linear_from_srgba(vec4 srgba) { + return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); +} + +void main() { + gl_Position = vec4( + 2.0 * a_pos.x / u_screen_size.x - 1.0, + 1.0 - 2.0 * a_pos.y / u_screen_size.y, + 0.0, + 1.0); + // egui encodes vertex colors in gamma spaces, so we must decode the colors here: + v_rgba = linear_from_srgba(a_srgba); + v_tc = a_tc; +} diff --git a/egui_glium/src/shader/vertex_140.glsl b/egui_glium/src/shader/vertex_140.glsl new file mode 100644 index 000000000..c1b9054e2 --- /dev/null +++ b/egui_glium/src/shader/vertex_140.glsl @@ -0,0 +1,31 @@ +#version 140 + +uniform vec2 u_screen_size; +in vec2 a_pos; +in vec4 a_srgba; // 0-255 sRGB +in vec2 a_tc; +out vec4 v_rgba; +out vec2 v_tc; + +// 0-1 linear from 0-255 sRGB +vec3 linear_from_srgb(vec3 srgb) { + bvec3 cutoff = lessThan(srgb, vec3(10.31475)); + vec3 lower = srgb / vec3(3294.6); + vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); + return mix(higher, lower, cutoff); +} + +vec4 linear_from_srgba(vec4 srgba) { + return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); +} + +void main() { + gl_Position = vec4( + 2.0 * a_pos.x / u_screen_size.x - 1.0, + 1.0 - 2.0 * a_pos.y / u_screen_size.y, + 0.0, + 1.0); + // egui encodes vertex colors in gamma spaces, so we must decode the colors here: + v_rgba = linear_from_srgba(a_srgba); + v_tc = a_tc; +} diff --git a/egui_glium/src/shader/vertex_300es.glsl b/egui_glium/src/shader/vertex_300es.glsl new file mode 100644 index 000000000..f587b2e37 --- /dev/null +++ b/egui_glium/src/shader/vertex_300es.glsl @@ -0,0 +1,32 @@ +#version 300 es + +precision mediump float; +uniform vec2 u_screen_size; +attribute vec2 a_pos; +attribute vec2 a_tc; +attribute vec4 a_srgba; +varying vec4 v_rgba; +varying vec2 v_tc; + +// 0-1 linear from 0-255 sRGB +vec3 linear_from_srgb(vec3 srgb) { + bvec3 cutoff = lessThan(srgb, vec3(10.31475)); + vec3 lower = srgb / vec3(3294.6); + vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 linear_from_srgba(vec4 srgba) { + return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); +} + +void main() { + gl_Position = vec4( + 2.0 * a_pos.x / u_screen_size.x - 1.0, + 1.0 - 2.0 * a_pos.y / u_screen_size.y, + 0.0, + 1.0); + // egui encodes vertex colors in gamma spaces, so we must decode the colors here: + v_rgba = linear_from_srgba(a_srgba); + v_tc = a_tc; +} diff --git a/egui_web/src/shader/fragment_100es.glsl b/egui_web/src/shader/fragment_100es.glsl new file mode 100644 index 000000000..3ca63b536 --- /dev/null +++ b/egui_web/src/shader/fragment_100es.glsl @@ -0,0 +1,45 @@ +#version 100 es + +precision mediump float; +uniform sampler2D u_sampler; +varying vec4 v_rgba; +varying vec2 v_tc; + +// 0-255 sRGB from 0-1 linear +vec3 srgb_from_linear(vec3 rgb) { + bvec3 cutoff = lessThan(rgb, vec3(0.0031308)); + vec3 lower = rgb * vec3(3294.6); + vec3 higher = vec3(269.025) * pow(rgb, vec3(1.0 / 2.4)) - vec3(14.025); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 srgba_from_linear(vec4 rgba) { + return vec4(srgb_from_linear(rgba.rgb), 255.0 * rgba.a); +} + +// 0-1 linear from 0-255 sRGB +vec3 linear_from_srgb(vec3 srgb) { + bvec3 cutoff = lessThan(srgb, vec3(10.31475)); + vec3 lower = srgb / vec3(3294.6); + vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 linear_from_srgba(vec4 srgba) { + return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); +} + +void main() { + // We must decode the colors, since WebGL doesn't come with sRGBA textures: + vec4 texture_rgba = linear_from_srgba(texture2D(u_sampler, v_tc) * 255.0); + + /// Multiply vertex color with texture color (in linear space). + gl_FragColor = v_rgba * texture_rgba; + + // We must gamma-encode again since WebGL doesn't support linear blending in the framebuffer. + gl_FragColor = srgba_from_linear(v_rgba * texture_rgba) / 255.0; + + // WebGL doesn't support linear blending in the framebuffer, + // so we apply this hack to at least get a bit closer to the desired blending: + gl_FragColor.a = pow(gl_FragColor.a, 1.6); // Empiric nonsense +} diff --git a/egui_web/src/shader/fragment_300es.glsl b/egui_web/src/shader/fragment_300es.glsl new file mode 100644 index 000000000..65b37c9be --- /dev/null +++ b/egui_web/src/shader/fragment_300es.glsl @@ -0,0 +1,33 @@ +#version 300 es + +precision mediump float; +uniform sampler2D u_sampler; +varying vec4 v_rgba; +varying vec2 v_tc; + +// 0-255 sRGB from 0-1 linear +vec3 srgb_from_linear(vec3 rgb) { + bvec3 cutoff = lessThan(rgb, vec3(0.0031308)); + vec3 lower = rgb * vec3(3294.6); + vec3 higher = vec3(269.025) * pow(rgb, vec3(1.0 / 2.4)) - vec3(14.025); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 srgba_from_linear(vec4 rgba) { + return vec4(srgb_from_linear(rgba.rgb), 255.0 * rgba.a); +} + +void main() { + // The texture is set up with `SRGB8_ALPHA8`, so no need to decode here! + vec4 texture_rgba = texture2D(u_sampler, v_tc); + + /// Multiply vertex color with texture color (in linear space). + gl_FragColor = v_rgba * texture_rgba; + + // We must gamma-encode again since WebGL doesn't support linear blending in the framebuffer. + gl_FragColor = srgba_from_linear(v_rgba * texture_rgba) / 255.0; + + // WebGL doesn't support linear blending in the framebuffer, + // so we apply this hack to at least get a bit closer to the desired blending: + gl_FragColor.a = pow(gl_FragColor.a, 1.6); // Empiric nonsense +} diff --git a/egui_web/src/shader/vertex_100es.glsl b/egui_web/src/shader/vertex_100es.glsl new file mode 100644 index 000000000..d7982452d --- /dev/null +++ b/egui_web/src/shader/vertex_100es.glsl @@ -0,0 +1,32 @@ +#version 100 es + +precision mediump float; +uniform vec2 u_screen_size; +attribute vec2 a_pos; +attribute vec2 a_tc; +attribute vec4 a_srgba; +varying vec4 v_rgba; +varying vec2 v_tc; + +// 0-1 linear from 0-255 sRGB +vec3 linear_from_srgb(vec3 srgb) { + bvec3 cutoff = lessThan(srgb, vec3(10.31475)); + vec3 lower = srgb / vec3(3294.6); + vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 linear_from_srgba(vec4 srgba) { + return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); +} + +void main() { + gl_Position = vec4( + 2.0 * a_pos.x / u_screen_size.x - 1.0, + 1.0 - 2.0 * a_pos.y / u_screen_size.y, + 0.0, + 1.0); + // egui encodes vertex colors in gamma spaces, so we must decode the colors here: + v_rgba = linear_from_srgba(a_srgba); + v_tc = a_tc; +} diff --git a/egui_web/src/shader/vertex_300es.glsl b/egui_web/src/shader/vertex_300es.glsl new file mode 100644 index 000000000..f587b2e37 --- /dev/null +++ b/egui_web/src/shader/vertex_300es.glsl @@ -0,0 +1,32 @@ +#version 300 es + +precision mediump float; +uniform vec2 u_screen_size; +attribute vec2 a_pos; +attribute vec2 a_tc; +attribute vec4 a_srgba; +varying vec4 v_rgba; +varying vec2 v_tc; + +// 0-1 linear from 0-255 sRGB +vec3 linear_from_srgb(vec3 srgb) { + bvec3 cutoff = lessThan(srgb, vec3(10.31475)); + vec3 lower = srgb / vec3(3294.6); + vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); + return mix(higher, lower, vec3(cutoff)); +} + +vec4 linear_from_srgba(vec4 srgba) { + return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); +} + +void main() { + gl_Position = vec4( + 2.0 * a_pos.x / u_screen_size.x - 1.0, + 1.0 - 2.0 * a_pos.y / u_screen_size.y, + 0.0, + 1.0); + // egui encodes vertex colors in gamma spaces, so we must decode the colors here: + v_rgba = linear_from_srgba(a_srgba); + v_tc = a_tc; +} diff --git a/egui_web/src/webgl1.rs b/egui_web/src/webgl1.rs index 97855c928..855d5becf 100644 --- a/egui_web/src/webgl1.rs +++ b/egui_web/src/webgl1.rs @@ -11,85 +11,6 @@ use egui::{ type Gl = WebGlRenderingContext; -const VERTEX_SHADER_SOURCE: &str = r#" - precision mediump float; - uniform vec2 u_screen_size; - attribute vec2 a_pos; - attribute vec2 a_tc; - attribute vec4 a_srgba; - varying vec4 v_rgba; - varying vec2 v_tc; - - // 0-1 linear from 0-255 sRGB - vec3 linear_from_srgb(vec3 srgb) { - bvec3 cutoff = lessThan(srgb, vec3(10.31475)); - vec3 lower = srgb / vec3(3294.6); - vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); - return mix(higher, lower, vec3(cutoff)); - } - - vec4 linear_from_srgba(vec4 srgba) { - return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); - } - - void main() { - gl_Position = vec4( - 2.0 * a_pos.x / u_screen_size.x - 1.0, - 1.0 - 2.0 * a_pos.y / u_screen_size.y, - 0.0, - 1.0); - // egui encodes vertex colors in gamma spaces, so we must decode the colors here: - v_rgba = linear_from_srgba(a_srgba); - v_tc = a_tc; - } -"#; - -const FRAGMENT_SHADER_SOURCE: &str = r#" - precision mediump float; - uniform sampler2D u_sampler; - varying vec4 v_rgba; - varying vec2 v_tc; - - // 0-255 sRGB from 0-1 linear - vec3 srgb_from_linear(vec3 rgb) { - bvec3 cutoff = lessThan(rgb, vec3(0.0031308)); - vec3 lower = rgb * vec3(3294.6); - vec3 higher = vec3(269.025) * pow(rgb, vec3(1.0 / 2.4)) - vec3(14.025); - return mix(higher, lower, vec3(cutoff)); - } - - vec4 srgba_from_linear(vec4 rgba) { - return vec4(srgb_from_linear(rgba.rgb), 255.0 * rgba.a); - } - - // 0-1 linear from 0-255 sRGB - vec3 linear_from_srgb(vec3 srgb) { - bvec3 cutoff = lessThan(srgb, vec3(10.31475)); - vec3 lower = srgb / vec3(3294.6); - vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); - return mix(higher, lower, vec3(cutoff)); - } - - vec4 linear_from_srgba(vec4 srgba) { - return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); - } - - void main() { - // We must decode the colors, since WebGL doesn't come with sRGBA textures: - vec4 texture_rgba = linear_from_srgba(texture2D(u_sampler, v_tc) * 255.0); - - /// Multiply vertex color with texture color (in linear space). - gl_FragColor = v_rgba * texture_rgba; - - // We must gamma-encode again since WebGL doesn't support linear blending in the framebuffer. - gl_FragColor = srgba_from_linear(v_rgba * texture_rgba) / 255.0; - - // WebGL doesn't support linear blending in the framebuffer, - // so we apply this hack to at least get a bit closer to the desired blending: - gl_FragColor.a = pow(gl_FragColor.a, 1.6); // Empiric nonsense - } -"#; - pub struct WebGlPainter { canvas_id: String, canvas: web_sys::HtmlCanvasElement, @@ -136,8 +57,16 @@ impl WebGlPainter { gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MIN_FILTER, Gl::LINEAR as i32); gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MAG_FILTER, Gl::LINEAR as i32); - let vert_shader = compile_shader(&gl, Gl::VERTEX_SHADER, VERTEX_SHADER_SOURCE)?; - let frag_shader = compile_shader(&gl, Gl::FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE)?; + let vert_shader = compile_shader( + &gl, + Gl::VERTEX_SHADER, + include_str!("shader/vertex_100es.glsl"), + )?; + let frag_shader = compile_shader( + &gl, + Gl::FRAGMENT_SHADER, + include_str!("shader/fragment_100es.glsl"), + )?; let program = link_program(&gl, [vert_shader, frag_shader].iter())?; let index_buffer = gl.create_buffer().ok_or("failed to create index_buffer")?; diff --git a/egui_web/src/webgl2.rs b/egui_web/src/webgl2.rs index a6115669b..7e741be4d 100644 --- a/egui_web/src/webgl2.rs +++ b/egui_web/src/webgl2.rs @@ -13,73 +13,6 @@ use egui::{ type Gl = WebGl2RenderingContext; -const VERTEX_SHADER_SOURCE: &str = r#" - precision mediump float; - uniform vec2 u_screen_size; - attribute vec2 a_pos; - attribute vec2 a_tc; - attribute vec4 a_srgba; - varying vec4 v_rgba; - varying vec2 v_tc; - - // 0-1 linear from 0-255 sRGB - vec3 linear_from_srgb(vec3 srgb) { - bvec3 cutoff = lessThan(srgb, vec3(10.31475)); - vec3 lower = srgb / vec3(3294.6); - vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4)); - return mix(higher, lower, vec3(cutoff)); - } - - vec4 linear_from_srgba(vec4 srgba) { - return vec4(linear_from_srgb(srgba.rgb), srgba.a / 255.0); - } - - void main() { - gl_Position = vec4( - 2.0 * a_pos.x / u_screen_size.x - 1.0, - 1.0 - 2.0 * a_pos.y / u_screen_size.y, - 0.0, - 1.0); - // egui encodes vertex colors in gamma spaces, so we must decode the colors here: - v_rgba = linear_from_srgba(a_srgba); - v_tc = a_tc; - } -"#; - -const FRAGMENT_SHADER_SOURCE: &str = r#" - precision mediump float; - uniform sampler2D u_sampler; - varying vec4 v_rgba; - varying vec2 v_tc; - - // 0-255 sRGB from 0-1 linear - vec3 srgb_from_linear(vec3 rgb) { - bvec3 cutoff = lessThan(rgb, vec3(0.0031308)); - vec3 lower = rgb * vec3(3294.6); - vec3 higher = vec3(269.025) * pow(rgb, vec3(1.0 / 2.4)) - vec3(14.025); - return mix(higher, lower, vec3(cutoff)); - } - - vec4 srgba_from_linear(vec4 rgba) { - return vec4(srgb_from_linear(rgba.rgb), 255.0 * rgba.a); - } - - void main() { - // The texture is set up with `SRGB8_ALPHA8`, so no need to decode here! - vec4 texture_rgba = texture2D(u_sampler, v_tc); - - /// Multiply vertex color with texture color (in linear space). - gl_FragColor = v_rgba * texture_rgba; - - // We must gamma-encode again since WebGL doesn't support linear blending in the framebuffer. - gl_FragColor = srgba_from_linear(v_rgba * texture_rgba) / 255.0; - - // WebGL doesn't support linear blending in the framebuffer, - // so we apply this hack to at least get a bit closer to the desired blending: - gl_FragColor.a = pow(gl_FragColor.a, 1.6); // Empiric nonsense - } -"#; - pub struct WebGl2Painter { canvas_id: String, canvas: web_sys::HtmlCanvasElement, @@ -126,8 +59,16 @@ impl WebGl2Painter { gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MIN_FILTER, Gl::LINEAR as i32); gl.tex_parameteri(Gl::TEXTURE_2D, Gl::TEXTURE_MAG_FILTER, Gl::LINEAR as i32); - let vert_shader = compile_shader(&gl, Gl::VERTEX_SHADER, VERTEX_SHADER_SOURCE)?; - let frag_shader = compile_shader(&gl, Gl::FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE)?; + let vert_shader = compile_shader( + &gl, + Gl::VERTEX_SHADER, + include_str!("shader/vertex_300es.glsl"), + )?; + let frag_shader = compile_shader( + &gl, + Gl::FRAGMENT_SHADER, + include_str!("shader/fragment_300es.glsl"), + )?; let program = link_program(&gl, [vert_shader, frag_shader].iter())?; let index_buffer = gl.create_buffer().ok_or("failed to create index_buffer")?;