diff options
Diffstat (limited to '')
| -rw-r--r-- | examples/integration_gl/Cargo.toml | 13 | ||||
| -rw-r--r-- | examples/integration_gl/README.md | 16 | ||||
| -rw-r--r-- | examples/integration_gl/src/controls.rs | 110 | ||||
| -rw-r--r-- | examples/integration_gl/src/main.rs | 175 | ||||
| -rw-r--r-- | examples/integration_gl/src/scene.rs | 93 | 
5 files changed, 407 insertions, 0 deletions
| diff --git a/examples/integration_gl/Cargo.toml b/examples/integration_gl/Cargo.toml new file mode 100644 index 00000000..80d7adad --- /dev/null +++ b/examples/integration_gl/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "integration_gl" +version = "0.1.0" +authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] +edition = "2018" +publish = false + +[dependencies] +iced_glutin = { path = "../../glutin" } +iced_glow = { path = "../../glow" } +iced_winit = { path = "../../winit" } +env_logger = "0.8" +glow = "0.6" diff --git a/examples/integration_gl/README.md b/examples/integration_gl/README.md new file mode 100644 index 00000000..87491508 --- /dev/null +++ b/examples/integration_gl/README.md @@ -0,0 +1,16 @@ +## Integration + +A demonstration of how to integrate Iced in an existing graphical OpenGL application. + +The __[`main`]__ file contains all the code of the example. + +<div align="center"> +  <a href="https://imgbox.com/9P9ETcod" target="_blank"><img src="https://images2.imgbox.com/2a/51/9P9ETcod_o.gif" alt="image host"/></a> +</div> + +You can run it with `cargo run`: +``` +cargo run --package integration_gl +``` + +[`main`]: src/main.rs diff --git a/examples/integration_gl/src/controls.rs b/examples/integration_gl/src/controls.rs new file mode 100644 index 00000000..13b7fbc2 --- /dev/null +++ b/examples/integration_gl/src/controls.rs @@ -0,0 +1,110 @@ +use iced_glow::Renderer; +use iced_glutin::{ +    slider, Align, Clipboard, Color, Column, Command, Element, Length, Program, +    Row, Slider, Text, +}; + +pub struct Controls { +    background_color: Color, +    sliders: [slider::State; 3], +} + +#[derive(Debug, Clone)] +pub enum Message { +    BackgroundColorChanged(Color), +} + +impl Controls { +    pub fn new() -> Controls { +        Controls { +            background_color: Color::BLACK, +            sliders: Default::default(), +        } +    } + +    pub fn background_color(&self) -> Color { +        self.background_color +    } +} + +impl Program for Controls { +    type Renderer = Renderer; +    type Message = Message; +    type Clipboard = Clipboard; + +    fn update( +        &mut self, +        message: Message, +        _clipboard: &mut Clipboard, +    ) -> Command<Message> { +        match message { +            Message::BackgroundColorChanged(color) => { +                self.background_color = color; +            } +        } + +        Command::none() +    } + +    fn view(&mut self) -> Element<Message, Renderer> { +        let [r, g, b] = &mut self.sliders; +        let background_color = self.background_color; + +        let sliders = Row::new() +            .width(Length::Units(500)) +            .spacing(20) +            .push( +                Slider::new(r, 0.0..=1.0, background_color.r, move |r| { +                    Message::BackgroundColorChanged(Color { +                        r, +                        ..background_color +                    }) +                }) +                .step(0.01), +            ) +            .push( +                Slider::new(g, 0.0..=1.0, background_color.g, move |g| { +                    Message::BackgroundColorChanged(Color { +                        g, +                        ..background_color +                    }) +                }) +                .step(0.01), +            ) +            .push( +                Slider::new(b, 0.0..=1.0, background_color.b, move |b| { +                    Message::BackgroundColorChanged(Color { +                        b, +                        ..background_color +                    }) +                }) +                .step(0.01), +            ); + +        Row::new() +            .width(Length::Fill) +            .height(Length::Fill) +            .align_items(Align::End) +            .push( +                Column::new() +                    .width(Length::Fill) +                    .align_items(Align::End) +                    .push( +                        Column::new() +                            .padding(10) +                            .spacing(10) +                            .push( +                                Text::new("Background color") +                                    .color(Color::WHITE), +                            ) +                            .push(sliders) +                            .push( +                                Text::new(format!("{:?}", background_color)) +                                    .size(14) +                                    .color(Color::WHITE), +                            ), +                    ), +            ) +            .into() +    } +} diff --git a/examples/integration_gl/src/main.rs b/examples/integration_gl/src/main.rs new file mode 100644 index 00000000..925102e3 --- /dev/null +++ b/examples/integration_gl/src/main.rs @@ -0,0 +1,175 @@ +mod controls; +mod scene; + +use controls::Controls; +use scene::Scene; + +use glow; +use glow::*; +use iced_glow::{Backend, Renderer, Settings, Viewport}; +use iced_glutin::glutin; +use iced_glutin::glutin::event::{Event, WindowEvent}; +use iced_glutin::glutin::event_loop::ControlFlow; +use iced_glutin::{program, Clipboard, Debug, Size}; +use iced_winit::conversion; +use iced_winit::winit; +use winit::{dpi::PhysicalPosition, event::ModifiersState}; + +pub fn main() { +    env_logger::init(); +    let (gl, event_loop, windowed_context, shader_version) = { +        let el = glutin::event_loop::EventLoop::new(); +        let wb = glutin::window::WindowBuilder::new() +            .with_title("OpenGL integration example") +            .with_inner_size(glutin::dpi::LogicalSize::new(1024.0, 768.0)); +        let windowed_context = glutin::ContextBuilder::new() +            .with_vsync(true) +            .build_windowed(wb, &el) +            .unwrap(); +        unsafe { +            let windowed_context = windowed_context.make_current().unwrap(); +            let gl = glow::Context::from_loader_function(|s| { +                windowed_context.get_proc_address(s) as *const _ +            }); +            // Enable auto-conversion from/to sRGB +            gl.enable(glow::FRAMEBUFFER_SRGB); + +            // Enable alpha blending +            gl.enable(glow::BLEND); +            gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA); + +            // Disable multisampling by default +            gl.disable(glow::MULTISAMPLE); +            (gl, el, windowed_context, "#version 410") +        } +    }; + +    let physical_size = windowed_context.window().inner_size(); +    let mut viewport = Viewport::with_physical_size( +        Size::new(physical_size.width, physical_size.height), +        windowed_context.window().scale_factor(), +    ); + +    let mut cursor_position = PhysicalPosition::new(-1.0, -1.0); +    let mut modifiers = ModifiersState::default(); +    let mut clipboard = Clipboard::connect(&windowed_context.window()); + +    let mut renderer = Renderer::new(Backend::new(&gl, Settings::default())); + +    let mut debug = Debug::new(); + +    let controls = Controls::new(); +    let mut state = program::State::new( +        controls, +        viewport.logical_size(), +        conversion::cursor_position(cursor_position, viewport.scale_factor()), +        &mut renderer, +        &mut debug, +    ); +    let mut resized = false; + +    event_loop.run(move |event, _, control_flow| { +        let scene = Scene::new(&gl, &shader_version); +        *control_flow = ControlFlow::Wait; + +        match event { +            Event::LoopDestroyed => return, +            Event::WindowEvent { event, .. } => { +                match event { +                    WindowEvent::CursorMoved { position, .. } => { +                        cursor_position = position; +                    } +                    WindowEvent::ModifiersChanged(new_modifiers) => { +                        modifiers = new_modifiers; +                    } +                    WindowEvent::Resized(physical_size) => { +                        viewport = Viewport::with_physical_size( +                            Size::new( +                                physical_size.width, +                                physical_size.height, +                            ), +                            windowed_context.window().scale_factor(), +                        ); + +                        resized = true; +                    } +                    WindowEvent::CloseRequested => { +                        scene.cleanup(&gl); +                        *control_flow = ControlFlow::Exit +                    } +                    _ => (), +                } + +                // Map window event to iced event +                if let Some(event) = iced_winit::conversion::window_event( +                    &event, +                    windowed_context.window().scale_factor(), +                    modifiers, +                ) { +                    state.queue_event(event); +                } +            } +            Event::MainEventsCleared => { +                // If there are events pending +                if !state.is_queue_empty() { +                    // We update iced +                    let _ = state.update( +                        viewport.logical_size(), +                        conversion::cursor_position( +                            cursor_position, +                            viewport.scale_factor(), +                        ), +                        &mut renderer, +                        &mut clipboard, +                        &mut debug, +                    ); + +                    // and request a redraw +                    windowed_context.window().request_redraw(); +                } +            } +            Event::RedrawRequested(_) => { +                if resized { +                    let size = windowed_context.window().inner_size(); + +                    unsafe { +                        gl.viewport( +                            0, +                            0, +                            size.width as i32, +                            size.height as i32, +                        ); +                    } + +                    resized = false; +                } + +                let program = state.program(); +                { +                    // We clear the frame +                    scene.clear(&gl, program.background_color()); + +                    // Draw the scene +                    scene.draw(&gl); +                } + +                // And then iced on top +                let mouse_interaction = renderer.backend_mut().draw( +                    &gl, +                    &viewport, +                    state.primitive(), +                    &debug.overlay(), +                ); +                // Update the mouse cursor +                windowed_context.window().set_cursor_icon( +                    iced_winit::conversion::mouse_interaction( +                        mouse_interaction, +                    ), +                ); + +                windowed_context.swap_buffers().unwrap(); +            } +            _ => (), +        } +    }); +} diff --git a/examples/integration_gl/src/scene.rs b/examples/integration_gl/src/scene.rs new file mode 100644 index 00000000..596381b3 --- /dev/null +++ b/examples/integration_gl/src/scene.rs @@ -0,0 +1,93 @@ +use glow::*; +use iced_glow::Color; + +pub struct Scene { +    program: glow::Program, +    vertex_array: glow::VertexArray, +} + +impl Scene { +    pub fn new(gl: &glow::Context, shader_version: &str) -> Self { +        unsafe { +            let vertex_array = gl +                .create_vertex_array() +                .expect("Cannot create vertex array"); +            gl.bind_vertex_array(Some(vertex_array)); + +            let program = gl.create_program().expect("Cannot create program"); + +            let (vertex_shader_source, fragment_shader_source) = ( +                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); +                }"#, +                r#"precision highp float; +                in vec2 vert; +                out vec4 color; +                void main() { +                    color = vec4(vert, 0.5, 1.0); +                }"#, +            ); + +            let shader_sources = [ +                (glow::VERTEX_SHADER, vertex_shader_source), +                (glow::FRAGMENT_SHADER, fragment_shader_source), +            ]; + +            let mut shaders = Vec::with_capacity(shader_sources.len()); + +            for (shader_type, shader_source) in shader_sources.iter() { +                let shader = gl +                    .create_shader(*shader_type) +                    .expect("Cannot create shader"); +                gl.shader_source(shader, &format!("{}\n{}", shader_version, shader_source)); +                gl.compile_shader(shader); +                if !gl.get_shader_compile_status(shader) { +                    panic!(gl.get_shader_info_log(shader)); +                } +                gl.attach_shader(program, shader); +                shaders.push(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); +            } + +            gl.use_program(Some(program)); +            Self { program, vertex_array } +        } +    } + +    pub fn clear(&self, gl: &glow::Context, background_color: Color) { +        let [r, g, b, a] = background_color.into_linear(); +        unsafe { +            gl.clear_color(r, g, b, a); +            gl.clear(glow::COLOR_BUFFER_BIT); +        } +    } + +    pub fn draw(&self, gl: &glow::Context) { +        unsafe { +            gl.draw_arrays(glow::TRIANGLES, 0, 3); +        } +    } + +    pub fn cleanup(&self, gl: &glow::Context) { +        unsafe { +            gl.delete_program(self.program); +            gl.delete_vertex_array(self.vertex_array); +        } +    } +}
\ No newline at end of file | 
