mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-23 11:28:28 +00:00
Flesh out examples
This commit is contained in:
parent
06b08508d9
commit
f1bd13b73e
@ -1,8 +1,6 @@
|
|||||||
//! A basic self-contained example to get you from zero-to-demo-window as fast
|
//! A basic self-contained example to get you from zero-to-demo-window as fast
|
||||||
//! as possible.
|
//! as possible.
|
||||||
|
|
||||||
use std::time::Instant;
|
|
||||||
|
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
use glutin::{event_loop::EventLoop, WindowedContext};
|
use glutin::{event_loop::EventLoop, WindowedContext};
|
||||||
use imgui_winit_support::WinitPlatform;
|
use imgui_winit_support::WinitPlatform;
|
||||||
@ -26,7 +24,6 @@ fn main() {
|
|||||||
.expect("failed to create renderer");
|
.expect("failed to create renderer");
|
||||||
|
|
||||||
// Standard winit event loop
|
// Standard winit event loop
|
||||||
let mut last_frame = Instant::now();
|
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop.run(move |event, _, control_flow| {
|
||||||
*control_flow = glutin::event_loop::ControlFlow::Wait;
|
*control_flow = glutin::event_loop::ControlFlow::Wait;
|
||||||
match event {
|
match event {
|
||||||
82
imgui-glow-renderer/examples/02_triangle.rs
Normal file
82
imgui-glow-renderer/examples/02_triangle.rs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//! A basic example showing imgui rendering together with some custom rendering.
|
||||||
|
//!
|
||||||
|
//! Note this example uses `RendererBuilder` rather than `auto_renderer` and
|
||||||
|
//! (because we're using the default "trivial" `ContextStateManager`)
|
||||||
|
//! therefore does not attempt to backup/restore OpenGL state.
|
||||||
|
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use glow::HasContext;
|
||||||
|
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
use utils::Triangler;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (event_loop, window) = utils::create_window("Hello, triangle!", glutin::GlRequest::Latest);
|
||||||
|
let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window);
|
||||||
|
let gl = utils::glow_context(&window);
|
||||||
|
|
||||||
|
let mut ig_renderer = imgui_glow_renderer::RendererBuilder::new()
|
||||||
|
.build_owning(gl, &mut imgui_context)
|
||||||
|
.expect("failed to create renderer");
|
||||||
|
let tri_renderer = Triangler::new(ig_renderer.gl_context(), "#version 330");
|
||||||
|
|
||||||
|
let mut last_frame = Instant::now();
|
||||||
|
event_loop.run(move |event, _, control_flow| {
|
||||||
|
*control_flow = glutin::event_loop::ControlFlow::Wait;
|
||||||
|
match event {
|
||||||
|
glutin::event::Event::NewEvents(_) => {
|
||||||
|
let now = Instant::now();
|
||||||
|
imgui_context
|
||||||
|
.io_mut()
|
||||||
|
.update_delta_time(now.duration_since(last_frame));
|
||||||
|
last_frame = now;
|
||||||
|
}
|
||||||
|
glutin::event::Event::MainEventsCleared => {
|
||||||
|
winit_platform
|
||||||
|
.prepare_frame(imgui_context.io_mut(), window.window())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
window.window().request_redraw();
|
||||||
|
}
|
||||||
|
glutin::event::Event::RedrawRequested(_) => {
|
||||||
|
{
|
||||||
|
let gl = ig_renderer.gl_context();
|
||||||
|
// This is required because, without the `StateBackupCsm`
|
||||||
|
// (which is provided by `auto_renderer` but not
|
||||||
|
// `RendererBuilder` by default), the OpenGL context is left
|
||||||
|
// in an arbitrary, dirty state
|
||||||
|
unsafe { gl.disable(glow::SCISSOR_TEST) };
|
||||||
|
tri_renderer.render(gl);
|
||||||
|
}
|
||||||
|
|
||||||
|
let ui = imgui_context.frame();
|
||||||
|
// Safety: internally, this reference just gets passed as a
|
||||||
|
// pointer to imgui, which handles the null pointer properly.
|
||||||
|
ui.show_demo_window(unsafe { &mut *std::ptr::null_mut() });
|
||||||
|
|
||||||
|
winit_platform.prepare_render(&ui, window.window());
|
||||||
|
let draw_data = ui.render();
|
||||||
|
ig_renderer
|
||||||
|
.render(&draw_data)
|
||||||
|
.expect("error rendering imgui");
|
||||||
|
|
||||||
|
window.swap_buffers().unwrap();
|
||||||
|
}
|
||||||
|
glutin::event::Event::WindowEvent {
|
||||||
|
event: glutin::event::WindowEvent::CloseRequested,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
*control_flow = glutin::event_loop::ControlFlow::Exit;
|
||||||
|
}
|
||||||
|
glutin::event::Event::LoopDestroyed => {
|
||||||
|
let gl = ig_renderer.gl_context();
|
||||||
|
tri_renderer.destroy(gl);
|
||||||
|
}
|
||||||
|
event => {
|
||||||
|
winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
79
imgui-glow-renderer/examples/03_triangle_gles.rs
Normal file
79
imgui-glow-renderer/examples/03_triangle_gles.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//! A basic example showing imgui rendering together with some custom rendering
|
||||||
|
//! using OpenGL ES, rather than full-fat OpenGL.
|
||||||
|
//!
|
||||||
|
//! Note this example uses `Renderer` rather than `OwningRenderer` and
|
||||||
|
//! therefore requries more lifetime-management of the OpenGL context.
|
||||||
|
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
mod utils;
|
||||||
|
|
||||||
|
use utils::Triangler;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (event_loop, window) = utils::create_window(
|
||||||
|
"Hello, triangle!",
|
||||||
|
glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0)),
|
||||||
|
);
|
||||||
|
let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window);
|
||||||
|
let gl = utils::glow_context(&window);
|
||||||
|
|
||||||
|
let mut ig_renderer = imgui_glow_renderer::RendererBuilder::new()
|
||||||
|
.with_context_state_manager(imgui_glow_renderer::StateBackupCsm::default())
|
||||||
|
.build_borrowing(&gl, &mut imgui_context)
|
||||||
|
.expect("failed to create renderer");
|
||||||
|
// Note the shader header now needs a precision specifier
|
||||||
|
let tri_renderer = Triangler::new(&gl, "#version 300 es\nprecision mediump float;");
|
||||||
|
|
||||||
|
let mut last_frame = Instant::now();
|
||||||
|
event_loop.run(move |event, _, control_flow| {
|
||||||
|
*control_flow = glutin::event_loop::ControlFlow::Wait;
|
||||||
|
match event {
|
||||||
|
glutin::event::Event::NewEvents(_) => {
|
||||||
|
let now = Instant::now();
|
||||||
|
imgui_context
|
||||||
|
.io_mut()
|
||||||
|
.update_delta_time(now.duration_since(last_frame));
|
||||||
|
last_frame = now;
|
||||||
|
}
|
||||||
|
glutin::event::Event::MainEventsCleared => {
|
||||||
|
winit_platform
|
||||||
|
.prepare_frame(imgui_context.io_mut(), window.window())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
window.window().request_redraw();
|
||||||
|
}
|
||||||
|
glutin::event::Event::RedrawRequested(_) => {
|
||||||
|
tri_renderer.render(&gl);
|
||||||
|
|
||||||
|
let ui = imgui_context.frame();
|
||||||
|
// Safety: internally, this reference just gets passed as a
|
||||||
|
// pointer to imgui, which handles the null pointer properly.
|
||||||
|
ui.show_demo_window(unsafe { &mut *std::ptr::null_mut() });
|
||||||
|
|
||||||
|
winit_platform.prepare_render(&ui, window.window());
|
||||||
|
let draw_data = ui.render();
|
||||||
|
ig_renderer
|
||||||
|
.render(&gl, &draw_data)
|
||||||
|
.expect("error rendering imgui");
|
||||||
|
|
||||||
|
window.swap_buffers().unwrap();
|
||||||
|
}
|
||||||
|
glutin::event::Event::WindowEvent {
|
||||||
|
event: glutin::event::WindowEvent::CloseRequested,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
*control_flow = glutin::event_loop::ControlFlow::Exit;
|
||||||
|
}
|
||||||
|
glutin::event::Event::LoopDestroyed => {
|
||||||
|
tri_renderer.destroy(&gl);
|
||||||
|
// Note, to be good citizens we should manually call destroy
|
||||||
|
// when the renderer does not own the GL context
|
||||||
|
ig_renderer.destroy(&gl);
|
||||||
|
}
|
||||||
|
event => {
|
||||||
|
winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
135
imgui-glow-renderer/examples/utils/mod.rs
Normal file
135
imgui-glow-renderer/examples/utils/mod.rs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
use glow::HasContext;
|
||||||
|
use glutin::{event_loop::EventLoop, GlRequest};
|
||||||
|
use imgui_winit_support::WinitPlatform;
|
||||||
|
|
||||||
|
pub type Window = glutin::WindowedContext<glutin::PossiblyCurrent>;
|
||||||
|
|
||||||
|
pub fn create_window(title: &str, gl_request: GlRequest) -> (EventLoop<()>, Window) {
|
||||||
|
let event_loop = glutin::event_loop::EventLoop::new();
|
||||||
|
let window = glutin::window::WindowBuilder::new()
|
||||||
|
.with_title(title)
|
||||||
|
.with_inner_size(glutin::dpi::LogicalSize::new(1024, 768));
|
||||||
|
let window = glutin::ContextBuilder::new()
|
||||||
|
.with_gl(gl_request)
|
||||||
|
.with_vsync(true)
|
||||||
|
.build_windowed(window, &event_loop)
|
||||||
|
.expect("could not create window");
|
||||||
|
let window = unsafe {
|
||||||
|
window
|
||||||
|
.make_current()
|
||||||
|
.expect("could not make window context current")
|
||||||
|
};
|
||||||
|
(event_loop, window)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn glow_context(window: &Window) -> glow::Context {
|
||||||
|
unsafe { glow::Context::from_loader_function(|s| window.get_proc_address(s).cast()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) {
|
||||||
|
let mut imgui_context = imgui::Context::create();
|
||||||
|
imgui_context.set_ini_filename(None);
|
||||||
|
|
||||||
|
let mut winit_platform = WinitPlatform::init(&mut imgui_context);
|
||||||
|
winit_platform.attach_window(
|
||||||
|
imgui_context.io_mut(),
|
||||||
|
window.window(),
|
||||||
|
imgui_winit_support::HiDpiMode::Rounded,
|
||||||
|
);
|
||||||
|
|
||||||
|
imgui_context
|
||||||
|
.fonts()
|
||||||
|
.add_font(&[imgui::FontSource::DefaultFontData { config: None }]);
|
||||||
|
|
||||||
|
imgui_context.io_mut().font_global_scale = (1.0 / winit_platform.hidpi_factor()) as f32;
|
||||||
|
|
||||||
|
(winit_platform, imgui_context)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Triangler {
|
||||||
|
pub program: <glow::Context as HasContext>::Program,
|
||||||
|
pub vertex_array: <glow::Context as HasContext>::VertexArray,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Triangler {
|
||||||
|
pub fn new(gl: &glow::Context, shader_header: &str) -> Self {
|
||||||
|
const VERTEX_SHADER_SOURCE: &str = r#"
|
||||||
|
const vec2 verts[3] = vec2[3](
|
||||||
|
vec2(0.5f, 1.0f),
|
||||||
|
vec2(0.0f, 0.0f),
|
||||||
|
vec2(1.0f, 0.0f)
|
||||||
|
);
|
||||||
|
|
||||||
|
out vec2 vert;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vert = verts[gl_VertexID];
|
||||||
|
gl_Position = vec4(vert - 0.5, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
const FRAGMENT_SHADER_SOURCE: &str = r#"
|
||||||
|
in vec2 vert;
|
||||||
|
out vec4 colour;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
colour = vec4(vert, 0.5, 1.0);
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let mut shaders = [
|
||||||
|
(glow::VERTEX_SHADER, VERTEX_SHADER_SOURCE, 0),
|
||||||
|
(glow::FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE, 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let vertex_array = gl
|
||||||
|
.create_vertex_array()
|
||||||
|
.expect("Cannot create vertex array");
|
||||||
|
|
||||||
|
let program = gl.create_program().expect("Cannot create program");
|
||||||
|
|
||||||
|
for (kind, source, handle) in &mut shaders {
|
||||||
|
let shader = gl.create_shader(*kind).expect("Cannot create shader");
|
||||||
|
gl.shader_source(shader, &format!("{}\n{}", shader_header, *source));
|
||||||
|
gl.compile_shader(shader);
|
||||||
|
if !gl.get_shader_compile_status(shader) {
|
||||||
|
panic!("{}", gl.get_shader_info_log(shader));
|
||||||
|
}
|
||||||
|
gl.attach_shader(program, shader);
|
||||||
|
*handle = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.link_program(program);
|
||||||
|
if !gl.get_program_link_status(program) {
|
||||||
|
panic!("{}", gl.get_program_info_log(program));
|
||||||
|
}
|
||||||
|
|
||||||
|
for &(_, _, shader) in &shaders {
|
||||||
|
gl.detach_shader(program, shader);
|
||||||
|
gl.delete_shader(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
program,
|
||||||
|
vertex_array,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(&self, gl: &glow::Context) {
|
||||||
|
unsafe {
|
||||||
|
gl.clear_color(0.05, 0.05, 0.1, 1.0);
|
||||||
|
gl.clear(glow::COLOR_BUFFER_BIT);
|
||||||
|
gl.use_program(Some(self.program));
|
||||||
|
gl.bind_vertex_array(Some(self.vertex_array));
|
||||||
|
gl.draw_arrays(glow::TRIANGLES, 0, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroy(&self, gl: &glow::Context) {
|
||||||
|
unsafe {
|
||||||
|
gl.delete_program(self.program);
|
||||||
|
gl.delete_vertex_array(self.vertex_array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user