Add integration_gl example
This commit is contained in:
parent
187413b452
commit
a646b11109
7 changed files with 410 additions and 2 deletions
|
|
@ -86,6 +86,7 @@ members = [
|
|||
"examples/tooltip",
|
||||
"examples/url_handler",
|
||||
"examples/menu",
|
||||
"examples/integration_gl",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
13
examples/integration_gl/Cargo.toml
Normal file
13
examples/integration_gl/Cargo.toml
Normal 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"
|
||||
16
examples/integration_gl/README.md
Normal file
16
examples/integration_gl/README.md
Normal 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
|
||||
110
examples/integration_gl/src/controls.rs
Normal file
110
examples/integration_gl/src/controls.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
175
examples/integration_gl/src/main.rs
Normal file
175
examples/integration_gl/src/main.rs
Normal 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();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
}
|
||||
93
examples/integration_gl/src/scene.rs
Normal file
93
examples/integration_gl/src/scene.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue