Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blinking UI Elements with imgui-rs, SDL2, and OpenGL in Rust: Seeking Resolution and Optimization #739

Open
ladroid opened this issue Jul 23, 2023 · 0 comments

Comments

@ladroid
Copy link

ladroid commented Jul 23, 2023

Describe the bug
During the execution of my application that uses the imgui-rs library in Rust with SDL2 and OpenGL, the application is constantly blinking or flickering.

To Reproduce
Steps to reproduce the behavior:

  1. Initialize SDL and its video subsystem.
  2. Create a new window with an OpenGL context.
  3. Set up the necessary attributes for the OpenGL context, including enabling double buffering and VSync.
  4. Create a glow context and an imgui context.
  5. Load a texture from a PNG file.
  6. Enter the main loop.
  7. Handle events, prepare the frame, and create the imgui UI.
  8. Render the texture and the imgui UI.
  9. Present the rendered content.

Example:

use glow::HasContext;
use imgui::Context;
use imgui_glow_renderer::AutoRenderer;
use imgui_sdl2_support::SdlPlatform;
use sdl2::{
    event::Event,
    video::{GLProfile, Window}
};
use sdl2::image::LoadTexture;
use std::path::Path;

// Create a new glow context.
fn glow_context(window: &Window) -> glow::Context {
    unsafe {
        glow::Context::from_loader_function(|s| window.subsystem().gl_get_proc_address(s) as _)
    }
}

fn main() {
    /* initialize SDL and its video subsystem */
    let sdl = sdl2::init().unwrap();
    let video_subsystem = sdl.video().unwrap();

    /* hint SDL to initialize an OpenGL 3.3 core profile context */
    let gl_attr = video_subsystem.gl_attr();

    gl_attr.set_context_version(3, 3);
    gl_attr.set_context_profile(GLProfile::Core);
    gl_attr.set_double_buffer(true);
    gl_attr.set_multisample_samples(4);
    gl_attr.set_framebuffer_srgb_compatible(true);

    /* create a new window, be sure to call opengl method on the builder when using glow! */
    let window = video_subsystem
        .window("Hello imgui-rs!", 1280, 720)
        .allow_highdpi()
        .opengl()
        .position_centered()
        .resizable()
        .build()
        .unwrap();

    /* create a new OpenGL context and make it current */
    let gl_context = window.gl_create_context().unwrap();
    window.gl_make_current(&gl_context).unwrap();
    unsafe { 
        sdl2::sys::SDL_GL_SetAttribute(sdl2_sys::SDL_GLattr::SDL_GL_DEPTH_SIZE, 24);
        sdl2::sys::SDL_GL_SetAttribute(sdl2_sys::SDL_GLattr::SDL_GL_STENCIL_SIZE, 8);
        sdl2::sys::SDL_GL_SetAttribute(sdl2_sys::SDL_GLattr::SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
    }

    let mut canvas = window.into_canvas().present_vsync().build().unwrap();

    /* enable vsync to cap framerate */
    canvas.window().subsystem().gl_set_swap_interval(1).unwrap();

    /* create new glow and imgui contexts */
    let gl = glow_context(&canvas.window());

    /* create context */
    let mut imgui = Context::create();

    /* disable creation of files on disc */
    imgui.set_ini_filename(None);
    imgui.set_log_filename(None);

    /* setup platform and renderer, and fonts to imgui */
    imgui
        .fonts()
        .add_font(&[imgui::FontSource::DefaultFontData { config: None }]);

    /* create platform and renderer */
    let mut platform = SdlPlatform::init(&mut imgui);
    let mut renderer = AutoRenderer::initialize(gl, &mut imgui).unwrap();

    /* load texture from PNG file */
    let texture_creator = canvas.texture_creator();
    let texture = texture_creator.load_texture(Path::new("path/to/texture.png")).unwrap();
    let texture_rect = Some(sdl2::rect::Rect::new(0, 0, 50, 50));

    /* start main loop */
    let mut event_pump = sdl.event_pump().unwrap();

    'main: loop {
        for event in event_pump.poll_iter() {
            /* pass all events to imgui platform */
            platform.handle_event(&mut imgui, &event);

            if let Event::Quit { .. } = event {
                break 'main;
            }
        }

        /* call prepare_frame before calling imgui.new_frame() */
        platform.prepare_frame(&mut imgui, &canvas.window(), &event_pump);

        let ui = imgui.new_frame();
        /* imgui UI */
        ui.show_demo_window(&mut true);

        /* render texture */
        canvas.clear();
        canvas.copy(&texture, None, texture_rect).unwrap();

        /* render */
        let draw_data = imgui.render();

        unsafe { renderer.gl_context().clear(glow::COLOR_BUFFER_BIT) };
        renderer.render(draw_data).unwrap();
        canvas.window().gl_swap_window();

        canvas.present();
    }
}

Expected behavior
I expect the UI components to be displayed without any blinking or flickering.

Screenshots
N/A

Please describe your environment

  • imgui-rs version 0.11.0
  • imgui-glow-renderer version 0.11.0
  • imgui-sdl2-support version 0.11.0
  • sdl2 version 0.34.5
  • Operating System: Windows 11

Other information
I came across this GitHub issue Dear Imgui issue which discusses a similar problem in the C++ version of imgui. I used some parts from there such as SDL_GL_DOUBLEBUFFER or SDL_GL_DEPTH_SIZE but it doesn't work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant