mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-12 14:08:37 +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
|
||||
//! as possible.
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
use glow::HasContext;
|
||||
use glutin::{event_loop::EventLoop, WindowedContext};
|
||||
use imgui_winit_support::WinitPlatform;
|
||||
@ -26,7 +24,6 @@ fn main() {
|
||||
.expect("failed to create renderer");
|
||||
|
||||
// Standard winit event loop
|
||||
let mut last_frame = Instant::now();
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
*control_flow = glutin::event_loop::ControlFlow::Wait;
|
||||
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