mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-23 11:28:28 +00:00
Merge pull request #44 from Gekkio/feature/gfx-renderer
gfx 0.16 support and renderer implementation
This commit is contained in:
commit
bc5dee3766
@ -5,7 +5,7 @@ rust:
|
|||||||
- stable
|
- stable
|
||||||
- beta
|
- beta
|
||||||
- nightly
|
- nightly
|
||||||
- 1.15.1
|
- 1.16.0
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
@ -18,8 +18,5 @@ before_install:
|
|||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
|
|
||||||
script:
|
script:
|
||||||
# 1.15 doesn't yet support cargo build --all
|
- cargo build --all --verbose
|
||||||
- cd imgui-sys && cargo build --verbose && cd ..
|
|
||||||
- cd imgui-glium-renderer && cargo build --verbose && cd ..
|
|
||||||
- cargo build --verbose
|
|
||||||
- cargo test --all --verbose
|
- cargo test --all --verbose
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- ImString owned type for strings
|
- ImString owned type for strings
|
||||||
|
- Experimental support for gfx-rs in imgui-sys
|
||||||
|
- Experimental renderer for gfx-rs
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
@ -32,6 +34,8 @@
|
|||||||
- Support for 2-4 -element float sliders
|
- Support for 2-4 -element float sliders
|
||||||
- `ImVec4::zero()`
|
- `ImVec4::zero()`
|
||||||
- `Into` array and tuple conversions for ImVec2 and ImVec4
|
- `Into` array and tuple conversions for ImVec2 and ImVec4
|
||||||
|
- gfx 0.15 support in imgui-sys
|
||||||
|
- gfx 0.15 renderer implementation
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@ -16,4 +16,4 @@ travis-ci = { repository = "gekkio/imgui-rs" }
|
|||||||
imgui-sys = { version = "0.0.14-pre", path = "imgui-sys" }
|
imgui-sys = { version = "0.0.14-pre", path = "imgui-sys" }
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["imgui-examples", "imgui-sys", "imgui-glium-renderer"]
|
members = ["imgui-examples", "imgui-sys", "imgui-gfx-renderer", "imgui-glium-renderer"]
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
**Still fairly experimental!**
|
**Still fairly experimental!**
|
||||||
|
|
||||||
Minimum Rust version: 1.15
|
Minimum Rust version: 1.16
|
||||||
|
|
||||||
[](https://travis-ci.org/Gekkio/imgui-rs)
|
[](https://travis-ci.org/Gekkio/imgui-rs)
|
||||||
[](https://crates.io/crates/imgui)
|
[](https://crates.io/crates/imgui)
|
||||||
|
|||||||
@ -9,7 +9,11 @@ license = "MIT/Apache-2.0"
|
|||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
gfx = "0.16"
|
||||||
|
gfx_window_glutin = "0.16"
|
||||||
glium = { version = "0.16", default-features = true }
|
glium = { version = "0.16", default-features = true }
|
||||||
|
glutin = "0.8"
|
||||||
imgui = { version = "0.0.14-pre", path = "../" }
|
imgui = { version = "0.0.14-pre", path = "../" }
|
||||||
|
imgui-gfx-renderer = { version = "0.0.14-pre", path = "../imgui-gfx-renderer" }
|
||||||
imgui-glium-renderer = { version = "0.0.14-pre", path = "../imgui-glium-renderer" }
|
imgui-glium-renderer = { version = "0.0.14-pre", path = "../imgui-glium-renderer" }
|
||||||
imgui-sys = { version = "0.0.14-pre", path = "../imgui-sys", features = ["glium"] }
|
imgui-sys = { version = "0.0.14-pre", path = "../imgui-sys", features = ["gfx", "glium"] }
|
||||||
|
|||||||
28
imgui-examples/examples/hello_gfx.rs
Normal file
28
imgui-examples/examples/hello_gfx.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
extern crate gfx;
|
||||||
|
extern crate gfx_window_glutin;
|
||||||
|
extern crate glutin;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate imgui;
|
||||||
|
extern crate imgui_gfx_renderer;
|
||||||
|
|
||||||
|
use imgui::*;
|
||||||
|
|
||||||
|
mod support_gfx;
|
||||||
|
|
||||||
|
const CLEAR_COLOR: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
support_gfx::run("hello_gfx.rs".to_owned(), CLEAR_COLOR, hello_world);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hello_world<'a>(ui: &Ui<'a>) {
|
||||||
|
ui.window(im_str!("Hello world"))
|
||||||
|
.size((300.0, 100.0), ImGuiSetCond_FirstUseEver)
|
||||||
|
.build(|| {
|
||||||
|
ui.text(im_str!("Hello world!"));
|
||||||
|
ui.text(im_str!("This...is...imgui-rs!"));
|
||||||
|
ui.separator();
|
||||||
|
let mouse_pos = ui.imgui().mouse_pos();
|
||||||
|
ui.text(im_str!("Mouse Position: ({:.1},{:.1})", mouse_pos.0, mouse_pos.1));
|
||||||
|
})
|
||||||
|
}
|
||||||
161
imgui-examples/examples/support_gfx/mod.rs
Normal file
161
imgui-examples/examples/support_gfx/mod.rs
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
use gfx;
|
||||||
|
use gfx::Device;
|
||||||
|
use gfx_window_glutin;
|
||||||
|
use glutin;
|
||||||
|
use glutin::{ElementState, MouseButton, MouseScrollDelta, VirtualKeyCode, TouchPhase, WindowEvent};
|
||||||
|
use imgui::{ImGui, Ui, ImGuiKey};
|
||||||
|
use imgui_gfx_renderer::Renderer;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
type ColorFormat = gfx::format::Rgba8;
|
||||||
|
type DepthFormat = gfx::format::DepthStencil;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Debug, Default)]
|
||||||
|
struct MouseState {
|
||||||
|
pos: (i32, i32),
|
||||||
|
pressed: (bool, bool, bool),
|
||||||
|
wheel: f32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run<F: FnMut(&Ui)>(title: String, clear_color: [f32; 4], mut run_ui: F) {
|
||||||
|
let mut imgui = ImGui::init();
|
||||||
|
|
||||||
|
let events_loop = glutin::EventsLoop::new();
|
||||||
|
let builder = glutin::WindowBuilder::new()
|
||||||
|
.with_title(title)
|
||||||
|
.with_dimensions(1024, 768)
|
||||||
|
.with_vsync();
|
||||||
|
let (window, mut device, mut factory, mut main_color, mut main_depth) =
|
||||||
|
gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder, &events_loop);
|
||||||
|
let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();
|
||||||
|
let mut renderer = Renderer::init(&mut imgui, &mut factory, main_color.clone())
|
||||||
|
.expect("Failed to initialize renderer");
|
||||||
|
|
||||||
|
configure_keys(&mut imgui);
|
||||||
|
|
||||||
|
let mut last_frame = Instant::now();
|
||||||
|
let mut mouse_state = MouseState::default();
|
||||||
|
let mut quit = false;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
events_loop.poll_events(|glutin::Event::WindowEvent{event, ..}| {
|
||||||
|
match event {
|
||||||
|
WindowEvent::Resized(_, _) => {
|
||||||
|
gfx_window_glutin::update_views(&window, &mut main_color, &mut main_depth);
|
||||||
|
renderer.update_render_target(main_color.clone());
|
||||||
|
}
|
||||||
|
WindowEvent::Closed => quit = true,
|
||||||
|
WindowEvent::KeyboardInput(state, _, code, _) => {
|
||||||
|
let pressed = state == ElementState::Pressed;
|
||||||
|
match code {
|
||||||
|
Some(VirtualKeyCode::Tab) => imgui.set_key(0, pressed),
|
||||||
|
Some(VirtualKeyCode::Left) => imgui.set_key(1, pressed),
|
||||||
|
Some(VirtualKeyCode::Right) => imgui.set_key(2, pressed),
|
||||||
|
Some(VirtualKeyCode::Up) => imgui.set_key(3, pressed),
|
||||||
|
Some(VirtualKeyCode::Down) => imgui.set_key(4, pressed),
|
||||||
|
Some(VirtualKeyCode::PageUp) => imgui.set_key(5, pressed),
|
||||||
|
Some(VirtualKeyCode::PageDown) => imgui.set_key(6, pressed),
|
||||||
|
Some(VirtualKeyCode::Home) => imgui.set_key(7, pressed),
|
||||||
|
Some(VirtualKeyCode::End) => imgui.set_key(8, pressed),
|
||||||
|
Some(VirtualKeyCode::Delete) => imgui.set_key(9, pressed),
|
||||||
|
Some(VirtualKeyCode::Back) => imgui.set_key(10, pressed),
|
||||||
|
Some(VirtualKeyCode::Return) => imgui.set_key(11, pressed),
|
||||||
|
Some(VirtualKeyCode::Escape) => quit = true,
|
||||||
|
Some(VirtualKeyCode::A) => imgui.set_key(13, pressed),
|
||||||
|
Some(VirtualKeyCode::C) => imgui.set_key(14, pressed),
|
||||||
|
Some(VirtualKeyCode::V) => imgui.set_key(15, pressed),
|
||||||
|
Some(VirtualKeyCode::X) => imgui.set_key(16, pressed),
|
||||||
|
Some(VirtualKeyCode::Y) => imgui.set_key(17, pressed),
|
||||||
|
Some(VirtualKeyCode::Z) => imgui.set_key(18, pressed),
|
||||||
|
Some(VirtualKeyCode::LControl) |
|
||||||
|
Some(VirtualKeyCode::RControl) => imgui.set_key_ctrl(pressed),
|
||||||
|
Some(VirtualKeyCode::LShift) |
|
||||||
|
Some(VirtualKeyCode::RShift) => imgui.set_key_shift(pressed),
|
||||||
|
Some(VirtualKeyCode::LAlt) |
|
||||||
|
Some(VirtualKeyCode::RAlt) => imgui.set_key_alt(pressed),
|
||||||
|
Some(VirtualKeyCode::LWin) |
|
||||||
|
Some(VirtualKeyCode::RWin) => imgui.set_key_super(pressed),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WindowEvent::MouseMoved(x, y) => mouse_state.pos = (x, y),
|
||||||
|
WindowEvent::MouseInput(state, MouseButton::Left) => {
|
||||||
|
mouse_state.pressed.0 = state == ElementState::Pressed
|
||||||
|
}
|
||||||
|
WindowEvent::MouseInput(state, MouseButton::Right) => {
|
||||||
|
mouse_state.pressed.1 = state == ElementState::Pressed
|
||||||
|
}
|
||||||
|
WindowEvent::MouseInput(state, MouseButton::Middle) => {
|
||||||
|
mouse_state.pressed.2 = state == ElementState::Pressed
|
||||||
|
}
|
||||||
|
WindowEvent::MouseWheel(MouseScrollDelta::LineDelta(_, y), TouchPhase::Moved) => {
|
||||||
|
mouse_state.wheel = y
|
||||||
|
}
|
||||||
|
WindowEvent::MouseWheel(MouseScrollDelta::PixelDelta(_, y), TouchPhase::Moved) => {
|
||||||
|
mouse_state.wheel = y
|
||||||
|
}
|
||||||
|
WindowEvent::ReceivedCharacter(c) => imgui.add_input_character(c),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let now = Instant::now();
|
||||||
|
let delta = now - last_frame;
|
||||||
|
let delta_s = delta.as_secs() as f32 + delta.subsec_nanos() as f32 / 1_000_000_000.0;
|
||||||
|
last_frame = now;
|
||||||
|
|
||||||
|
update_mouse(&mut imgui, &mut mouse_state);
|
||||||
|
|
||||||
|
let size_points = window.get_inner_size_points().unwrap();
|
||||||
|
let size_pixels = window.get_inner_size_pixels().unwrap();
|
||||||
|
|
||||||
|
let ui = imgui.frame(size_points, size_pixels, delta_s);
|
||||||
|
|
||||||
|
run_ui(&ui);
|
||||||
|
|
||||||
|
encoder.clear(&mut main_color, clear_color);
|
||||||
|
|
||||||
|
renderer.render(ui, &mut factory, &mut encoder)
|
||||||
|
.expect("Rendering failed");
|
||||||
|
encoder.flush(&mut device);
|
||||||
|
window.swap_buffers().unwrap();
|
||||||
|
device.cleanup();
|
||||||
|
|
||||||
|
if quit { break }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configure_keys(imgui: &mut ImGui) {
|
||||||
|
imgui.set_imgui_key(ImGuiKey::Tab, 0);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::LeftArrow, 1);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::RightArrow, 2);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::UpArrow, 3);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::DownArrow, 4);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::PageUp, 5);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::PageDown, 6);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::Home, 7);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::End, 8);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::Delete, 9);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::Backspace, 10);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::Enter, 11);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::Escape, 12);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::A, 13);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::C, 14);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::V, 15);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::X, 16);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::Y, 17);
|
||||||
|
imgui.set_imgui_key(ImGuiKey::Z, 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_mouse(imgui: &mut ImGui, mouse_state: &mut MouseState) {
|
||||||
|
let scale = imgui.display_framebuffer_scale();
|
||||||
|
imgui.set_mouse_pos(mouse_state.pos.0 as f32 / scale.0,
|
||||||
|
mouse_state.pos.1 as f32 / scale.1);
|
||||||
|
imgui.set_mouse_down(&[mouse_state.pressed.0,
|
||||||
|
mouse_state.pressed.1,
|
||||||
|
mouse_state.pressed.2,
|
||||||
|
false,
|
||||||
|
false]);
|
||||||
|
imgui.set_mouse_wheel(mouse_state.wheel / scale.1);
|
||||||
|
mouse_state.wheel = 0.0;
|
||||||
|
}
|
||||||
14
imgui-gfx-renderer/Cargo.toml
Normal file
14
imgui-gfx-renderer/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "imgui-gfx-renderer"
|
||||||
|
version = "0.0.14-pre"
|
||||||
|
authors = ["Joonas Javanainen <joonas.javanainen@gmail.com>", "imgui-rs contributors"]
|
||||||
|
description = "gfx renderer for the imgui crate"
|
||||||
|
homepage = "https://github.com/gekkio/imgui-rs"
|
||||||
|
repository = "https://github.com/gekkio/imgui-rs"
|
||||||
|
license = "MIT/Apache-2.0"
|
||||||
|
categories = ["gui", "rendering"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
gfx = "0.16"
|
||||||
|
imgui = { version = "0.0.14-pre", path = "../" }
|
||||||
|
imgui-sys = { version = "0.0.14-pre", path = "../imgui-sys", features = ["gfx"] }
|
||||||
173
imgui-gfx-renderer/src/lib.rs
Normal file
173
imgui-gfx-renderer/src/lib.rs
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate gfx;
|
||||||
|
extern crate imgui;
|
||||||
|
|
||||||
|
use gfx::{Bind, Bundle, CommandBuffer, Encoder, Factory, IntoIndexBuffer, Rect, Resources, Slice};
|
||||||
|
use gfx::handle::{Buffer, RenderTargetView};
|
||||||
|
use gfx::traits::FactoryExt;
|
||||||
|
use imgui::{DrawList, ImDrawIdx, ImDrawVert, ImGui, Ui};
|
||||||
|
|
||||||
|
pub type RendererResult<T> = Result<T, RendererError>;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum RendererError {
|
||||||
|
Update(gfx::UpdateError<usize>),
|
||||||
|
Buffer(gfx::buffer::CreationError),
|
||||||
|
Pipeline(gfx::PipelineStateError<String>),
|
||||||
|
Combined(gfx::CombinedError)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<gfx::UpdateError<usize>> for RendererError {
|
||||||
|
fn from(e: gfx::UpdateError<usize>) -> RendererError { RendererError::Update(e) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<gfx::buffer::CreationError> for RendererError {
|
||||||
|
fn from(e: gfx::buffer::CreationError) -> RendererError { RendererError::Buffer(e) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<gfx::PipelineStateError<String>> for RendererError {
|
||||||
|
fn from(e: gfx::PipelineStateError<String>) -> RendererError { RendererError::Pipeline(e) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<gfx::CombinedError> for RendererError {
|
||||||
|
fn from(e: gfx::CombinedError) -> RendererError { RendererError::Combined(e) }
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_defines!{
|
||||||
|
pipeline pipe {
|
||||||
|
vertex_buffer: gfx::VertexBuffer<ImDrawVert> = (),
|
||||||
|
matrix: gfx::Global<[[f32; 4]; 4]> = "matrix",
|
||||||
|
tex: gfx::TextureSampler<[f32; 4]> = "tex",
|
||||||
|
out: gfx::BlendTarget<gfx::format::Rgba8> = ("Target0", gfx::state::MASK_ALL, gfx::preset::blend::ALPHA),
|
||||||
|
scissor: gfx::Scissor = (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Renderer<R: Resources> {
|
||||||
|
bundle: Bundle<R, pipe::Data<R>>,
|
||||||
|
index_buffer: Buffer<R, u16>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: Resources> Renderer<R> {
|
||||||
|
pub fn init<F: Factory<R>>(imgui: &mut ImGui,
|
||||||
|
factory: &mut F,
|
||||||
|
out: RenderTargetView<R, gfx::format::Rgba8>)
|
||||||
|
-> RendererResult<Renderer<R>> {
|
||||||
|
let pso = factory.create_pipeline_simple(include_bytes!("shader/vert_110.glsl"),
|
||||||
|
include_bytes!("shader/frag_110.glsl"),
|
||||||
|
pipe::new())?;
|
||||||
|
let vertex_buffer = factory.create_buffer::<ImDrawVert>(256,
|
||||||
|
gfx::buffer::Role::Vertex,
|
||||||
|
gfx::memory::Usage::Dynamic,
|
||||||
|
Bind::empty())?;
|
||||||
|
let index_buffer = factory.create_buffer::<ImDrawIdx>(256,
|
||||||
|
gfx::buffer::Role::Index,
|
||||||
|
gfx::memory::Usage::Dynamic,
|
||||||
|
Bind::empty())?;
|
||||||
|
let (_, texture) = imgui.prepare_texture(|handle| {
|
||||||
|
factory.create_texture_immutable_u8::<gfx::format::Rgba8>(gfx::texture::Kind::D2(handle.width as u16, handle.height as u16, gfx::texture::AaMode::Single), &[handle.pixels])
|
||||||
|
})?;
|
||||||
|
// TODO: set texture id in imgui
|
||||||
|
let sampler = factory.create_sampler_linear();
|
||||||
|
let data = pipe::Data {
|
||||||
|
vertex_buffer: vertex_buffer,
|
||||||
|
matrix: [[0.0, 0.0, 0.0, 0.0],
|
||||||
|
[0.0, 0.0, 0.0, 0.0],
|
||||||
|
[0.0, 0.0, -1.0, 0.0],
|
||||||
|
[-1.0, 1.0, 0.0, 1.0]],
|
||||||
|
tex: (texture, sampler),
|
||||||
|
out: out,
|
||||||
|
scissor: Rect {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
w: 0,
|
||||||
|
h: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let slice = Slice {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
base_vertex: 0,
|
||||||
|
instances: None,
|
||||||
|
buffer: index_buffer.clone().into_index_buffer(factory),
|
||||||
|
};
|
||||||
|
Ok(Renderer {
|
||||||
|
bundle: Bundle::new(slice, pso, data),
|
||||||
|
index_buffer: index_buffer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn update_render_target(&mut self, out: RenderTargetView<R, gfx::format::Rgba8>) {
|
||||||
|
self.bundle.data.out = out;
|
||||||
|
}
|
||||||
|
pub fn render<'a, F: Factory<R>, C: CommandBuffer<R>>(&mut self,
|
||||||
|
ui: Ui<'a>,
|
||||||
|
factory: &mut F,
|
||||||
|
encoder: &mut Encoder<R, C>)
|
||||||
|
-> RendererResult<()> {
|
||||||
|
let (width, height) = ui.imgui().display_size();
|
||||||
|
|
||||||
|
if width == 0.0 || height == 0.0 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
self.bundle.data.matrix = [[2.0 / width as f32, 0.0, 0.0, 0.0],
|
||||||
|
[0.0, -2.0 / height as f32, 0.0, 0.0],
|
||||||
|
[0.0, 0.0, -1.0, 0.0],
|
||||||
|
[-1.0, 1.0, 0.0, 1.0]];
|
||||||
|
|
||||||
|
ui.render(|ui, draw_list| self.render_draw_list(ui, factory, encoder, draw_list))
|
||||||
|
}
|
||||||
|
fn render_draw_list<'a, F: Factory<R>, C: CommandBuffer<R>>(&mut self,
|
||||||
|
ui: &'a Ui<'a>,
|
||||||
|
factory: &mut F,
|
||||||
|
encoder: &mut Encoder<R, C>,
|
||||||
|
draw_list: DrawList<'a>)
|
||||||
|
-> RendererResult<()> {
|
||||||
|
let (scale_width, scale_height) = ui.imgui().display_framebuffer_scale();
|
||||||
|
|
||||||
|
self.bundle.slice.start = 0;
|
||||||
|
for cmd in draw_list.cmd_buffer {
|
||||||
|
// TODO: check cmd.texture_id
|
||||||
|
|
||||||
|
self.upload_vertex_buffer(factory, encoder, draw_list.vtx_buffer)?;
|
||||||
|
self.upload_index_buffer(factory, encoder, draw_list.idx_buffer)?;
|
||||||
|
|
||||||
|
self.bundle.slice.end = self.bundle.slice.start + cmd.elem_count;
|
||||||
|
self.bundle.data.scissor = Rect {
|
||||||
|
x: (cmd.clip_rect.x * scale_width) as u16,
|
||||||
|
y: (cmd.clip_rect.y * scale_height) as u16,
|
||||||
|
w: ((cmd.clip_rect.z - cmd.clip_rect.x).abs() * scale_width) as u16,
|
||||||
|
h: ((cmd.clip_rect.w - cmd.clip_rect.y).abs() * scale_height) as u16,
|
||||||
|
};
|
||||||
|
self.bundle.encode(encoder);
|
||||||
|
self.bundle.slice.start = self.bundle.slice.end;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn upload_vertex_buffer<F: Factory<R>, C: CommandBuffer<R>>(&mut self,
|
||||||
|
factory: &mut F,
|
||||||
|
encoder: &mut Encoder<R, C>,
|
||||||
|
vtx_buffer: &[ImDrawVert])
|
||||||
|
-> RendererResult<()> {
|
||||||
|
if self.bundle.data.vertex_buffer.len() < vtx_buffer.len() {
|
||||||
|
self.bundle.data.vertex_buffer = factory.create_buffer::<ImDrawVert>(vtx_buffer.len(),
|
||||||
|
gfx::buffer::Role::Vertex,
|
||||||
|
gfx::memory::Usage::Dynamic,
|
||||||
|
Bind::empty())?;
|
||||||
|
}
|
||||||
|
Ok(encoder.update_buffer(&self.bundle.data.vertex_buffer, vtx_buffer, 0)?)
|
||||||
|
}
|
||||||
|
fn upload_index_buffer<F: Factory<R>, C: CommandBuffer<R>>(&mut self,
|
||||||
|
factory: &mut F,
|
||||||
|
encoder: &mut Encoder<R, C>,
|
||||||
|
idx_buffer: &[ImDrawIdx])
|
||||||
|
-> RendererResult<()> {
|
||||||
|
if self.index_buffer.len() < idx_buffer.len() {
|
||||||
|
self.index_buffer = factory.create_buffer::<ImDrawIdx>(idx_buffer.len(),
|
||||||
|
gfx::buffer::Role::Index,
|
||||||
|
gfx::memory::Usage::Dynamic,
|
||||||
|
Bind::empty())?;
|
||||||
|
self.bundle.slice.buffer = self.index_buffer.clone().into_index_buffer(factory);
|
||||||
|
}
|
||||||
|
Ok(encoder.update_buffer(&self.index_buffer, idx_buffer, 0)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
10
imgui-gfx-renderer/src/shader/frag_110.glsl
Normal file
10
imgui-gfx-renderer/src/shader/frag_110.glsl
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#version 110
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
varying vec2 f_uv;
|
||||||
|
varying vec4 f_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_FragColor = f_color * texture2D(tex, f_uv.st);
|
||||||
|
}
|
||||||
12
imgui-gfx-renderer/src/shader/frag_140.glsl
Normal file
12
imgui-gfx-renderer/src/shader/frag_140.glsl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#version 140
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
in vec2 f_uv;
|
||||||
|
in vec4 f_color;
|
||||||
|
|
||||||
|
out vec4 Target0;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Target0 = f_color * texture(tex, f_uv.st);
|
||||||
|
}
|
||||||
16
imgui-gfx-renderer/src/shader/vert_110.glsl
Normal file
16
imgui-gfx-renderer/src/shader/vert_110.glsl
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#version 110
|
||||||
|
|
||||||
|
uniform mat4 matrix;
|
||||||
|
|
||||||
|
attribute vec2 pos;
|
||||||
|
attribute vec2 uv;
|
||||||
|
attribute vec4 col;
|
||||||
|
|
||||||
|
varying vec2 f_uv;
|
||||||
|
varying vec4 f_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
f_uv = uv;
|
||||||
|
f_color = col;
|
||||||
|
gl_Position = matrix * vec4(pos.xy, 0, 1);
|
||||||
|
}
|
||||||
16
imgui-gfx-renderer/src/shader/vert_140.glsl
Normal file
16
imgui-gfx-renderer/src/shader/vert_140.glsl
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#version 140
|
||||||
|
|
||||||
|
uniform mat4 matrix;
|
||||||
|
|
||||||
|
in vec2 pos;
|
||||||
|
in vec2 uv;
|
||||||
|
in vec4 col;
|
||||||
|
|
||||||
|
out vec2 f_uv;
|
||||||
|
out vec4 f_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
f_uv = uv;
|
||||||
|
f_color = col;
|
||||||
|
gl_Position = matrix * vec4(pos.xy, 0, 1);
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ build = "build.rs"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "0.8"
|
bitflags = "0.8"
|
||||||
glium = { version = "0.16", default-features = false, optional = true }
|
glium = { version = "0.16", default-features = false, optional = true }
|
||||||
|
gfx = { version = "0.16", optional = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
gcc = "0.3"
|
gcc = "0.3"
|
||||||
|
|||||||
58
imgui-sys/src/gfx_support.rs
Normal file
58
imgui-sys/src/gfx_support.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
use gfx::format::{Format, Formatted, U8Norm};
|
||||||
|
use gfx::pso::buffer::{Element, ElemOffset, Structure};
|
||||||
|
use gfx::traits::Pod;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
use super::{ImDrawVert, ImVec2};
|
||||||
|
|
||||||
|
unsafe impl Pod for ImDrawVert {}
|
||||||
|
|
||||||
|
impl Structure<Format> for ImDrawVert {
|
||||||
|
fn query(name: &str) -> Option<Element<Format>> {
|
||||||
|
// array query hack from gfx_impl_struct_meta macro
|
||||||
|
let (sub_name, big_offset) = {
|
||||||
|
let mut split = name.split(|c| c == '[' || c == ']');
|
||||||
|
let _ = split.next().unwrap();
|
||||||
|
match split.next() {
|
||||||
|
Some(s) => {
|
||||||
|
let array_id: ElemOffset = s.parse().unwrap();
|
||||||
|
let sub_name = match split.next() {
|
||||||
|
Some(s) if s.starts_with('.') => &s[1..],
|
||||||
|
_ => name,
|
||||||
|
};
|
||||||
|
(sub_name, array_id * (mem::size_of::<ImDrawVert>() as ElemOffset))
|
||||||
|
}
|
||||||
|
None => (name, 0),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let dummy: &ImDrawVert = unsafe { mem::transmute(0usize) };
|
||||||
|
match sub_name {
|
||||||
|
"pos" => {
|
||||||
|
Some(Element {
|
||||||
|
format: <ImVec2 as Formatted>::get_format(),
|
||||||
|
offset: unsafe { mem::transmute::<_, usize>(&dummy.pos) } as ElemOffset +
|
||||||
|
big_offset,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"uv" => {
|
||||||
|
Some(Element {
|
||||||
|
format: <ImVec2 as Formatted>::get_format(),
|
||||||
|
offset: unsafe { mem::transmute::<_, usize>(&dummy.uv) } as ElemOffset +
|
||||||
|
big_offset,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"col" => {
|
||||||
|
Some(Element {
|
||||||
|
format: <[U8Norm; 4] as Formatted>::get_format(),
|
||||||
|
offset: unsafe { mem::transmute::<_, usize>(&dummy.col) } as ElemOffset +
|
||||||
|
big_offset,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_format! {
|
||||||
|
ImVec2: R32_G32 = Vec2<Float>
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
use glium::vertex::{Attribute, AttributeType, Vertex, VertexFormat};
|
use glium::vertex::{Attribute, AttributeType, Vertex, VertexFormat};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw::{c_float};
|
use std::os::raw::c_float;
|
||||||
|
|
||||||
use super::{ImDrawVert, ImVec2, ImVec4};
|
use super::{ImDrawVert, ImVec2, ImVec4};
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,10 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
|
|
||||||
|
#[cfg(feature = "gfx")]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate gfx;
|
||||||
|
|
||||||
#[cfg(feature = "glium")]
|
#[cfg(feature = "glium")]
|
||||||
extern crate glium;
|
extern crate glium;
|
||||||
|
|
||||||
@ -11,6 +15,9 @@ use std::mem;
|
|||||||
use std::os::raw::{c_char, c_float, c_int, c_short, c_uchar, c_uint, c_ushort, c_void};
|
use std::os::raw::{c_char, c_float, c_int, c_short, c_uchar, c_uint, c_ushort, c_void};
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
|
#[cfg(feature = "gfx")]
|
||||||
|
mod gfx_support;
|
||||||
|
|
||||||
#[cfg(feature = "glium")]
|
#[cfg(feature = "glium")]
|
||||||
mod glium_support;
|
mod glium_support;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user