arjunnair / egui_sdl2_gl Goto Github PK
View Code? Open in Web Editor NEWEgui backend for SDL2 + OpenGL
License: MIT License
Egui backend for SDL2 + OpenGL
License: MIT License
The gradients should all match up seamlessly.
To reproduce:
let mut egui_test = egui_demo_lib::ColorTest::default();
egui::Window::new("Test").show(&egui_ctx, |ui| {
let mut none = None;
egui_test.ui(ui,&mut none);
});
I think the problem might be with the srgb conversion/blending code, but I'm not sure.
Hi! I was wondering if you were going to also add Vulkan support later. Preferably, using the ash
crate.
For someone new to OpenGL it is unclear how to integrate this with an existing application. Since paint_jobs
calls gl::Clear(gl::COLOR_BUFFER_BIT)
, it will overwrite anything drawn before it. Notably, egui_glium does this, too, so there might be a good reason, but to a newcomer it's unclear how this is supposed to work. It might be possible to paint the gui first and use depth testing to draw your content under the gui, but if this is the intended usage it would be nice if it was documented somewhere how to do that.
Hey there, thanks for the amazing work with this crate!
Any idea how I could show egui in a SDL2 canvas (2D pixels)?
It works well for 3D, but for 2D I am just seeing a black screen.
I can mouse over the UI elements and see the cursor change, but it only renders everything completely black.
egui master recently got support for IMEs (Input Method Editors; emilk/egui#248). These new events should be handled by egui_sdl2_gl
.
When detecting window resize events, it doesn't check which window is resized. When multiple windows are used, events from other windows will affect egui. The fix is to check like this: https://github.com/Yamakaky/gyromouse/blob/gui/src/backend/sdl/overlay.rs#L221-L225.
https://github.com/ArjunNair/egui_sdl2_gl/blob/main/src/lib.rs#L54-L57
The current crate depends upon egui
version 0.2.0
while the current version in 0.4.0
.
Please bump the crate dependency's version.
i am not shure if this is a mistake on my side. i am also not entirely familiar with the internal ways this crate operates. when i try to create my own gl texture an render a cube with that texture on it, for some reason some user textures i created earlier with the painter are being rendered on the cube. is it possible that this has something to do with the way this backend operates? it is really strange because when i draw my cube mesh i literally just set the active texture, bind the buffer and set the uniform for the shader. thats all i do. the texture that is displayed also varies from app launch to app launch, which is even more strange.
Take all of this with a grain of salt; I'm far from an opengl expert, theres are just my findings when trying to use this code with glfw instead of sdl2 (which is a tiny tiny change, it would be incredibly easy to set this up so that both can be used).
let program = link_program(vert_shader, frag_shader);
let mut index_buffer = 0;
let mut pos_buffer = 0;
let mut tc_buffer = 0;
let mut color_buffer = 0;
gl::GenVertexArrays(1, &mut index_buffer);
gl::BindVertexArray(index_buffer);
//This overwrites the ID of the generated vertex array with data for a new buffer, effectively leaking video memory.
gl::GenBuffers(1, &mut index_buffer);
gl::GenBuffers(1, &mut pos_buffer);
gl::GenBuffers(1, &mut tc_buffer);
gl::GenBuffers(1, &mut color_buffer);
You generate a vertex array into index_buffer, then later forget about the vertex array by overwriting it with another buffer. Later on I see index_buffer used to store indices (ELEMENT_ARRAY_BUFFER). But then later on it gets deleted in cleanup with gl::DeleteVertexArrays(1, &self.index_buffer); - which should be gl::DeleteBuffers if it is used to store indices.
I think newer versions of opengl require you to bind a vertex array before you're allowed to do anything; my driver already pre-generates one when I make a new context. What ends up happening in my code is this:
Set up vertex array 1.
bind vertex array 1.
Buffer triangle vertices/indices yadayada to it. (the vertex and index buffer are internally linked to the vertex_array)
Setup a shader.
egui code starts
set up vertex array 2
bind vertex array 2
overwrite vertex array with regular buffer - 2 is lost -> we get index buffer 12 back for all I care, this depends on GL state that we don't know about
setup other buffers and data?
main loop:
do inputs yadayada
draw my own triangle:
bind vertex array 1
bind shader for vertex array 1 (for some reason, it seems you DO have to rebind shaders, they seem detached from vertex arrays)
draw vertex array 1
egui draws:
DONT BIND VERTEX ARRAY
buffer data -> this data overwrites the triangle I drew before because opengl considers it bound
draw vertex array 1 because it is still bound by opengl
swap buffers: I can see my own triangle and the egui stuff being drawn. On to the 2nd frame
draw my own triangle:
bind vertex array 1 -> this has been overwritten by egui!
does it draw egui? does it draw a triangle? does it draw garabage? I honestly don't know...
draw vertex array 1??
egui draws:
DONT BIND VERTEX ARRAY
buffer data -> data was already overwritten, nothing really happens
draw vertex array 1 because it is still bound by opengl
swap buffers: I can no longer see my own triangle, I can only see the egui stuff being rendered.
The fix is very simple, just setup proper VA managemen. Let me add my changes to a PR.
The project is currently using egui ~0.23 and sdl2 ~0.35, but the up-to-date versions are egui ~0.26 and sdl2 ~0.36
I have a project that is using sdl2 and raw opengl that I want to integrate this crate into so I can use egui, but unfortunately even after following the examples I can't get anything but the panel backgrounds to render. So for instance, if I make a full screen panel the whole screen becomes gray, and if I make a bottom panel then a line along the bottom of the screen becomes gray (while the rest of the screen shows the other stuff I'm rendering), but none of the labels or interface widgets that I add to the panels actually render. Here's the basic layout of my code:
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let gl_attr = video_subsystem.gl_attr();
// set up opengl settings
let mut window = video_subsystem
.window("window title", 1920, 1080)
.opengl()
.build()
.unwrap();
///////// Initialize OpenGL
let _image_context = sdl2::image::init(sdl2::image::InitFlag::all());
let _gl_context = window.gl_create_context().unwrap();
let _gl =
gl::load_with(|s| video_subsystem.gl_get_proc_address(s) as *const std::os::raw::c_void);
unsafe {
gl::Viewport(0, 0, w as gl::types::GLint, h as gl::types::GLint);
gl::ClearColor(0.0, 0.0, 0.0, 1.0);
gl::Enable(gl::DEPTH_TEST);
}
///////// Initialize eGUI
let shader_ver = ShaderVersion::Default;
let (mut painter, mut egui_state) =
egui_backend::with_sdl2(&window, shader_ver, egui_sdl2_gl::DpiScaling::Default);
let mut egui_ctx = egui::Context::default();
// ...
loop {
egui_state.input.time = Some(start_time.elapsed().as_secs_f64());
// clear screen
// render other opengl stuff
egui_ctx.begin_frame(egui_state.input.take());
egui::TopBottomPanel::bottom("bottom_panel").show(&egui_ctx, |ui| {
ui.label("Hello world");
});
let FullOutput {
platform_output,
repaint_after,
textures_delta,
shapes,
} = egui_ctx.end_frame();
egui_state.process_output(&window, &platform_output);
let paint_jobs = egui_ctx.tessellate(shapes);
painter.paint_jobs(None, textures_delta, paint_jobs);
window.gl_swap_window();
}
And here's a link to my actual code: https://github.com/alexispurslane/opengl-project/blob/7d57cc212feb73e006457670f589e5f29423729d/src/main.rs#L32
Is there something wrong with the order I'm doing things in, or a step I'm missing? Or maybe some dependency I've left out? I'm suffering from some serious neurological problems right now so I'm sure it's some silly mistake I've missed. Thank you for your help! :D
P.S. I'm honestly really lucky to have found a relatively actively maintained project that slots so perfectly into the intersection of technologies I'm already using, so I really appreciate the work you are doing.
Example with egui_sdl2_gl + egui_wgpu: https://github.com/Yamakaky/gyromouse/blob/gui/src/backend/sdl/gui.rs
This mirrors https://github.com/hasenbanck/egui_example where the wgpu and winit crates are separated.
See changelog:
Looks like an easy enough fix at first glance... I could have a go at making a pull request if you don't feel like fixing it.
0.18.1 was recently released, along with 0.17.0 a few months ago, which had some breaking changes. It looks like the main ones to worry about in that regard are (From the changelog - https://github.com/emilk/egui/blob/master/CHANGELOG.md)
For integrations:
Output has now been renamed PlatformOutput and Context::run now returns the new FullOutput (https://github.com/emilk/egui/pull/1292).
FontImage has been replaced by TexturesDelta (found in FullOutput), describing what textures were loaded and freed each frame (https://github.com/emilk/egui/pull/1110).
The painter must support partial texture updates (https://github.com/emilk/egui/pull/1149).
Added RawInput::max_texture_side which should be filled in with e.g. GL_MAX_TEXTURE_SIZE (https://github.com/emilk/egui/pull/1154).
In my project egui + this crate have rendering problem (see screenshot in bottom).
Preparing:
let sdl = sdl2::init().unwrap();
let video_subsystem = sdl.video().unwrap();
let window = video_subsystem
.window("Rat Engine", w, h)
.opengl()
.resizable()
.build()
.unwrap();
video_subsystem.gl_attr().set_context_version(3, 3);
video_subsystem.gl_attr().set_context_profile(GLProfile::Core);
let _gl_context = window.gl_create_context().unwrap();
gl::load_with(|s| video_subsystem.gl_get_proc_address(s) as *const std::os::raw::c_void);
let (mut egui_painter, egui_state) = egui_backend::with_sdl2(&window, ShaderVersion::Default, DpiScaling::Custom(1.0));
let egui_ctx = egui::Context::default();
Looped logic:
while self.is_running {
for event in event_pump.poll_iter() {
self.window.egui_state.process_input(&self.window.sdl_window, event, &mut self.window.egui_painter);
}
unsafe {
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
}
self.window.egui_state.input.time = Some(start_time.elapsed().as_secs_f64());
self.window.egui_ctx.begin_frame(self.window.egui_state.input.take());
egui::Window::new("Console")
.show(&self.window.egui_ctx, |ui| {
ui.button("Hello World!");
ui.label("Hello World!");
ui.label("Hello World!");
ui.label("Hello World!");
});
let FullOutput {
platform_output,
repaint_after,
textures_delta,
shapes,
} = self.window.egui_ctx.end_frame();
self.window.egui_state.process_output(&self.window.sdl_window, &platform_output);
let paint_jobs = self.window.egui_ctx.tessellate(shapes);
self.window.egui_painter.paint_jobs(None, textures_delta, paint_jobs);
self.window.sdl_window.gl_swap_window();
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.