Closed Titaniumtown closed 2 years ago
I haven't tried it, but I really would like for it to work.
@expenses claims to be using egui-wgpu
for WebGL in https://github.com/emilk/egui/pull/1671 - maybe they have some input?
Yep, but it's currently locked to using webgl and not webgpu: https://github.com/emilk/egui/blob/bd5f553c3a33fd9de0f396634044117bd519342d/egui-wgpu/Cargo.toml#L43
We'd just need to remove this feature to get it work for both backends
I assume this cannot be done as easily as eframe::start_web
... how did you do it exactly?
We are using egui-wgpu successfully on wasm (with the webgl2 backend currently, though i don't think it should be different for webgpu).
We have an existing wgpu context and custom event loop, input events etc (driven by typescript side), i'm not au fait with how eframe does it, but we followed the 'integrations' part of the eframe repo and got it up and running fairly seamlessly. Which bit are you struggling with in particular? @Titaniumtown
I managed to create a minimum working example using egui-wgpu with a wgpu backend and wasm32 target, see https://github.com/geolehmann/egui-wgpu_wasm_example (event handling is not yet included), which took me way longer than it should. I had to use my own fork of egui tho with some fixes (I used some code from the fork of @expenses ).
I also found another working example: https://github.com/pierscowburn/egui_wgpu_failure_case, but here still the older egui-wgpu-backend crate is used.
@geolehmann thanks for that example! I notice that you use winit (and egui-winit) on the web, which is interesting (see https://github.com/emilk/egui/issues/1032).
I have done my own barebones integration of egui on top of a 'raw' wgpu app originally based on the 'learn wgpu' tutorials. this runs on native and in browser via WASM wth wgpu (no webgl fallback). I also have hooked up basic mouse move and button click events as i required them.
I dont really have a 'releaseable' example app i can publish (and I use camel case which likely makes me an heretic in the wider rust community) but, in case its a helpful to anyone - my renderers state struct has the following added:
guiContext: egui::Context,
guiRenderPass: egui_wgpu::renderer::RenderPass,
guiScreenDescriptor: egui_wgpu::renderer::ScreenDescriptor,
guiInput: egui::RawInput,
guiMousePositionInPoints: egui::Pos2, //cache our mouse position as we need it for events
these are initialised as follows:
let guiContext = egui::Context::default();
let guiRenderPass = egui_wgpu::renderer::RenderPass::new(&device, config.format, 1);
let guiScreenDescriptor = egui_wgpu::renderer::ScreenDescriptor {
size_in_pixels: [config.width, config.height],
pixels_per_point: 2.0,
};
let guiInput = egui::RawInput::default();
let guiMousePositionInPoints = egui::pos2(0.0, 0.0);
and the main part of the rendering looks like:
// at beginning of render function create a second encoder to handle the gui drawing commands
let mut guiEncoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Gui Encoder"),
});
{
self.guiContext.begin_frame(self.guiInput.take());
//some code to draw a few widgets - rot is a rotation in radians for the displayed model
egui::Window::new("My Window").show(&self.guiContext, |ui| {
ui.label("Hello World!");
if ui.button("A Button").clicked() {
log::warn!("CLICKED BUTTON");
};
ui.add(
egui::Slider::new(&mut self.rot, 0.0..=6.25)
.text("rot")
.fixed_decimals(2),
);
});
//code needed to render the gui
let guiOutput = self.guiContext.end_frame();
let prims = self.guiContext.tessellate(guiOutput.shapes);
self.guiRenderPass.update_buffers(
&self.device,
&self.queue,
&prims[..],
&self.guiScreenDescriptor,
);
for (id, image_delta) in &guiOutput.textures_delta.set {
self.guiRenderPass
.update_texture(&self.device, &self.queue, *id, image_delta);
}
self.guiRenderPass.execute(
&mut guiEncoder,
&view,
&prims[..],
&self.guiScreenDescriptor,
None,
);
}
self.queue.submit(iter::once(guiEncoder.finish()));
output.present();
example of input gathering from the existing winit handlers is:
WindowEvent::CursorMoved {
device_id,
position,
modifiers,
..
} => {
//log::warn!("CURSOR {:#?} {:#?}", position.x, position.y);
let pos = egui::pos2(
position.x as f32 / self.guiScreenDescriptor.pixels_per_point,
position.y as f32 / self.guiScreenDescriptor.pixels_per_point,
);
self.guiMousePositionInPoints = pos;
let pointerEvent = egui::Event::PointerMoved(pos);
self.guiInput.events.push(pointerEvent);
true
}
I am a bit of a rust newbie (Most of my experience in this sort of thing is with raw Vulkan and C++) so have just followed my nose as to how to make this work, but this produces a usable gui overlaid on top of my existing 3d rendered output. If anyone else wants to try the same approach i'm happy to provide more detail
@metacean please use backticks for code
like this
I would be willing to provide an example, as I've got my own egui + winit + wgpu integration working on wasm!
But I would like to first await some responses to #2022 and #2023 :)
How could one use the wgpu integration for egui on wasm? I can't find a way to do this. Is this possible?