Add integration_gl example

This commit is contained in:
Tamás Szelei 2020-11-15 23:51:13 +01:00 committed by Héctor Ramón Jiménez
parent 187413b452
commit a646b11109
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
7 changed files with 410 additions and 2 deletions

View file

@ -86,6 +86,7 @@ members = [
"examples/tooltip",
"examples/url_handler",
"examples/menu",
"examples/integration_gl",
]
[dependencies]

View file

@ -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"

View file

@ -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

View file

@ -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()
}
}

View file

@ -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();
}
_ => (),
}
});
}

View file

@ -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);
}
}
}

View file

@ -4,14 +4,14 @@
//!
//! [`glow`]: https://github.com/grovesNL/glow
//! [`iced_native`]: https://github.com/hecrj/iced/tree/master/native
#![deny(missing_docs)]
//#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
#![forbid(rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg))]
mod backend;
mod program;
pub mod program;
mod quad;
mod text;
mod triangle;