mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 05:40:03 -04:00
Make egui_glow painter to work on web (#868)
Add WebGL1 and WebGL2 support to glow painter. Add "glow" feature to egui_web to use the glow painter there. Make winit an optional part of egui_glow
This commit is contained in:
@@ -5,6 +5,11 @@ pub use egui::{pos2, Color32};
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
fn create_painter(canvas_id: &str) -> Result<Box<dyn Painter>, JsValue> {
|
||||
#[cfg(feature = "glow")]
|
||||
return Ok(Box::new(crate::glow_wrapping::WrappedGlowPainter::new(
|
||||
canvas_id,
|
||||
)));
|
||||
#[cfg(not(feature = "glow"))]
|
||||
if let Ok(webgl2_painter) = webgl2::WebGl2Painter::new(canvas_id) {
|
||||
console_log("Using WebGL2 backend");
|
||||
Ok(Box::new(webgl2_painter))
|
||||
@@ -167,7 +172,7 @@ impl AppRunner {
|
||||
|
||||
fn integration_info(&self) -> epi::IntegrationInfo {
|
||||
epi::IntegrationInfo {
|
||||
name: "egui_web",
|
||||
name: self.painter.name(),
|
||||
web_info: Some(epi::WebInfo {
|
||||
web_location_hash: location_hash().unwrap_or_default(),
|
||||
}),
|
||||
|
||||
130
egui_web/src/glow_wrapping.rs
Normal file
130
egui_web/src/glow_wrapping.rs
Normal file
@@ -0,0 +1,130 @@
|
||||
use crate::web_sys::{WebGl2RenderingContext, WebGlRenderingContext};
|
||||
use crate::{canvas_element_or_die, console_error};
|
||||
use egui::{ClippedMesh, Rgba, Texture};
|
||||
use egui_glow::glow;
|
||||
use epi::TextureAllocator;
|
||||
use wasm_bindgen::JsValue;
|
||||
use web_sys::HtmlCanvasElement;
|
||||
|
||||
pub(crate) struct WrappedGlowPainter {
|
||||
pub(crate) gl_ctx: glow::Context,
|
||||
pub(crate) canvas: HtmlCanvasElement,
|
||||
pub(crate) canvas_id: String,
|
||||
pub(crate) painter: egui_glow::Painter,
|
||||
}
|
||||
|
||||
impl WrappedGlowPainter {
|
||||
pub fn new(canvas_id: &str) -> Self {
|
||||
let canvas = canvas_element_or_die(canvas_id);
|
||||
let gl_ctx = init_glow_context_from_canvas(&canvas);
|
||||
let dimension = [canvas.width() as i32, canvas.height() as i32];
|
||||
let painter = egui_glow::Painter::new(&gl_ctx, Some(dimension))
|
||||
.map_err(|error| {
|
||||
console_error(format!(
|
||||
"some error occurred in initializing glow painter\n {}",
|
||||
error
|
||||
))
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
gl_ctx,
|
||||
canvas,
|
||||
canvas_id: canvas_id.to_owned(),
|
||||
painter,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl crate::Painter for WrappedGlowPainter {
|
||||
fn as_tex_allocator(&mut self) -> &mut dyn TextureAllocator {
|
||||
&mut self.painter
|
||||
}
|
||||
|
||||
fn debug_info(&self) -> String {
|
||||
format!(
|
||||
"Stored canvas size: {} x {}",
|
||||
self.canvas.width(),
|
||||
self.canvas.height(),
|
||||
)
|
||||
}
|
||||
|
||||
fn canvas_id(&self) -> &str {
|
||||
&self.canvas_id
|
||||
}
|
||||
|
||||
fn upload_egui_texture(&mut self, texture: &Texture) {
|
||||
self.painter.upload_egui_texture(&self.gl_ctx, texture)
|
||||
}
|
||||
|
||||
fn clear(&mut self, clear_color: Rgba) {
|
||||
let canvas_dimension = [self.canvas.width(), self.canvas.height()];
|
||||
egui_glow::painter::clear(&self.gl_ctx, canvas_dimension, clear_color)
|
||||
}
|
||||
|
||||
fn paint_meshes(
|
||||
&mut self,
|
||||
clipped_meshes: Vec<ClippedMesh>,
|
||||
pixels_per_point: f32,
|
||||
) -> Result<(), JsValue> {
|
||||
let canvas_dimension = [self.canvas.width(), self.canvas.height()];
|
||||
self.painter.paint_meshes(
|
||||
canvas_dimension,
|
||||
&self.gl_ctx,
|
||||
pixels_per_point,
|
||||
clipped_meshes,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"egui_web(glow)"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_glow_context_from_canvas(canvas: &HtmlCanvasElement) -> glow::Context {
|
||||
use wasm_bindgen::JsCast;
|
||||
let ctx = canvas.get_context("webgl2");
|
||||
if let Ok(ctx) = ctx {
|
||||
crate::console_log("webgl found");
|
||||
if let Some(ctx) = ctx {
|
||||
crate::console_log("webgl 2 selected");
|
||||
let gl_ctx = ctx.dyn_into::<web_sys::WebGl2RenderingContext>().unwrap();
|
||||
glow::Context::from_webgl2_context(gl_ctx)
|
||||
} else {
|
||||
let ctx = canvas.get_context("webgl");
|
||||
if let Ok(ctx) = ctx {
|
||||
crate::console_log("falling back to webgl1");
|
||||
if let Some(ctx) = ctx {
|
||||
crate::console_log("webgl1 selected");
|
||||
|
||||
let gl_ctx = ctx.dyn_into::<web_sys::WebGlRenderingContext>().unwrap();
|
||||
crate::console_log("success");
|
||||
glow::Context::from_webgl1_context(gl_ctx)
|
||||
} else {
|
||||
panic!("tried webgl1 but can't get context");
|
||||
}
|
||||
} else {
|
||||
panic!("tried webgl1 but can't get context");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("tried webgl2 but something went wrong");
|
||||
}
|
||||
}
|
||||
|
||||
trait DummyWebGLConstructor {
|
||||
fn from_webgl1_context(context: web_sys::WebGlRenderingContext) -> Self;
|
||||
|
||||
fn from_webgl2_context(context: web_sys::WebGl2RenderingContext) -> Self;
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl DummyWebGLConstructor for glow::Context {
|
||||
fn from_webgl1_context(_context: WebGlRenderingContext) -> Self {
|
||||
panic!("you cant use egui_web(glow) on native")
|
||||
}
|
||||
|
||||
fn from_webgl2_context(_context: WebGl2RenderingContext) -> Self {
|
||||
panic!("you cant use egui_web(glow) on native")
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
#![warn(clippy::all, missing_crate_level_docs, rust_2018_idioms)]
|
||||
|
||||
pub mod backend;
|
||||
#[cfg(feature = "glow")]
|
||||
mod glow_wrapping;
|
||||
mod painter;
|
||||
pub mod screen_reader;
|
||||
pub mod webgl1;
|
||||
|
||||
@@ -17,4 +17,6 @@ pub trait Painter {
|
||||
clipped_meshes: Vec<egui::ClippedMesh>,
|
||||
pixels_per_point: f32,
|
||||
) -> Result<(), JsValue>;
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
@@ -538,6 +538,10 @@ impl crate::Painter for WebGlPainter {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"egui_web(webgl1)"
|
||||
}
|
||||
}
|
||||
|
||||
struct PostProcess {
|
||||
|
||||
@@ -516,6 +516,10 @@ impl crate::Painter for WebGl2Painter {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"egui_web(webgl2)"
|
||||
}
|
||||
}
|
||||
|
||||
/// Uses a framebuffer to render everything in linear color space and convert it back to sRGB
|
||||
|
||||
Reference in New Issue
Block a user