Improve documentation about how to write a painter for egui

This commit is contained in:
Emil Ernerfeldt 2021-01-17 02:06:26 +01:00
parent 8598c365a1
commit 2854a84728
5 changed files with 44 additions and 20 deletions

View file

@ -183,9 +183,13 @@ loop {
}
```
For a reference OpenGL backend, [see the `egui_glium` painter](https://github.com/emilk/egui/blob/master/egui_glium/src/painter.rs).
For a reference OpenGL backend, see [the `egui_glium` painter](https://github.com/emilk/egui/blob/master/egui_glium/src/painter.rs) or [the `egui_web` `WebGL` painter](https://github.com/emilk/egui/blob/master/egui_web/src/webgl1.rs).
#### Debugging your integration
### Debugging your integration
#### Things look jagged
* Turn off backface culling.
#### My text is blurry
@ -194,9 +198,13 @@ For a reference OpenGL backend, [see the `egui_glium` painter](https://github.co
#### My windows are too transparent or too dark
* Make sure your texture sampler is clamped.
* Make sure you consider sRGB (gamma) in your shaders.
* Egui uses premultiplied alpha, so make sure your blending function is `(ONE, ONE_MINUS_SRC_ALPHA)`
* Egui uses premultiplied alpha, so make sure your blending function is `(ONE, ONE_MINUS_SRC_ALPHA)`.
* Make sure your texture sampler is clamped (`GL_CLAMP_TO_EDGE`).
* Use an sRGBA-aware texture if available (e.g. `GL_SRGB8_ALPHA8`).
* Otherwise: remember to decode gamma in the fragment shader.
* Decode the gamma of the incoming vertex colors in your vertex shader.
* Turn on sRGBA/linear framebuffer if available (`GL_FRAMEBUFFER_SRGB`).
* Otherwise: gamma-encode the colors before you write them again.
## Other

View file

@ -43,6 +43,7 @@ const VERTEX_SHADER_SOURCE: &str = r#"
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;
}
@ -226,6 +227,9 @@ impl Painter {
..Default::default()
};
// Egui outputs triangles in both winding orders:
let backface_culling = glium::BackfaceCullingMode::CullingDisabled;
// Transform clip rect to physical pixels:
let clip_min_x = pixels_per_point * clip_rect.min.x;
let clip_min_y = pixels_per_point * clip_rect.min.y;
@ -245,6 +249,7 @@ impl Painter {
let params = glium::DrawParameters {
blend,
backface_culling,
scissor: Some(glium::Rect {
left: clip_min_x,
bottom: height_in_pixels - clip_max_y,

View file

@ -39,6 +39,7 @@ const VERTEX_SHADER_SOURCE: &str = r#"
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;
}
@ -75,7 +76,13 @@ const FRAGMENT_SHADER_SOURCE: &str = r#"
}
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,
@ -456,12 +463,11 @@ impl crate::Painter for WebGlPainter {
let gl = &self.gl;
gl.disable(Gl::SCISSOR_TEST);
gl.viewport(
0,
0,
self.canvas.width() as i32,
self.canvas.height() as i32,
);
let width = self.canvas.width() as i32;
let height = self.canvas.height() as i32;
gl.viewport(0, 0, width, height);
let clear_color: Color32 = clear_color.into();
gl.clear_color(
clear_color[0] as f32 / 255.0,

View file

@ -41,6 +41,7 @@ const VERTEX_SHADER_SOURCE: &str = r#"
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;
}
@ -65,8 +66,13 @@ const FRAGMENT_SHADER_SOURCE: &str = r#"
}
void main() {
// The texture is set up with `SRGB8_ALPHA8`, so no need to decode here!
vec4 texture_rgba = texture2D(u_sampler, v_tc);
// gl_FragColor = v_rgba * texture_rgba;
/// 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,
@ -420,8 +426,6 @@ impl crate::Painter for WebGl2Painter {
let gl = &self.gl;
gl.bind_texture(Gl::TEXTURE_2D, Some(&self.egui_texture));
// TODO: https://developer.mozilla.org/en-US/docs/Web/API/EXT_sRGB
// https://www.khronos.org/registry/webgl/extensions/EXT_sRGB/
let level = 0;
let internal_format = Gl::SRGB8_ALPHA8;
let border = 0;
@ -448,12 +452,11 @@ impl crate::Painter for WebGl2Painter {
let gl = &self.gl;
gl.disable(Gl::SCISSOR_TEST);
gl.viewport(
0,
0,
self.canvas.width() as i32,
self.canvas.height() as i32,
);
let width = self.canvas.width() as i32;
let height = self.canvas.height() as i32;
gl.viewport(0, 0, width, height);
let clear_color: Color32 = clear_color.into();
gl.clear_color(
clear_color[0] as f32 / 255.0,

View file

@ -24,6 +24,8 @@ pub struct Vertex {
#[derive(Clone, Debug, Default)]
pub struct Triangles {
/// Draw as triangles (i.e. the length is always multiple of three).
///
/// Egui is NOT consistent with what winding order it uses, so turn off backface culling.
pub indices: Vec<u32>,
/// The vertex data indexed by `indices`.