#gtk #gfx #opengl #epoxy #glarea

gfx-gtk

gtk::GlArea中嵌入GFX渲染的集成助手

4个版本 (破坏性更新)

使用旧的Rust 2015

0.4.0 2019年2月22日
0.3.0 2018年10月13日
0.2.0 2018年10月13日
0.1.0 2018年9月29日

#509 in 图形API

Apache-2.0

44KB
693

gfx-gtk

使用Gfx (pre-ll)库渲染到gtk-rs GLArea的简单桥梁库。

使用[epoxy]进行GL加载,因此不需要像glutinwinit这样的GL窗口/加载管理。

以下是一个简短的分步列表,以启动集成

添加Cargo依赖项

[dependencies]
gfx_gtk = "0.3"

导入crate和包

extern crate gfx_gtk;

use gfx_gtk::formats;
use gfx_gtk::GlRenderContext;

选择一些渲染格式和抗锯齿模式

const MSAA: gfx::texture::AaMode = formats::MSAA_4X;
type RenderColorFormat = formats::DefaultRenderColorFormat;
type RenderDepthFormat = formats::DefaultRenderDepthFormat;

编写渲染回调

您需要实现[GlRenderCallback]和[GlPostprocessCallback]特质(后者可以采用默认实现)

struct SimpleRenderCallback {
	...
}

impl gfx_gtk::GlRenderCallback<RenderColorFormat, RenderDepthFormat> for SimpleRenderCallback {
	fn render(
		&mut self,
		gfx_context: &mut gfx_gtk::GlGfxContext,
		viewport: &gfx_gtk::Viewport,
		frame_buffer: &gfx_gtk::GlFrameBuffer<RenderColorFormat>,
		depth_buffer: &gfx_gtk::GlDepthBuffer<RenderDepthFormat>,
	) -> gfx_gtk::Result<gfx_gtk::GlRenderCallbackStatus> {
		gfx_context.encoder.draw(...);
		Ok(gfx_gtk::GlRenderCallbackStatus::Continue)
	}
}

impl gfx_gtk::GlPostprocessCallback<RenderColorFormat, RenderDepthFormat> for SimpleRenderCallback {}

加载GL函数

gfx_gtk::load();

连接小部件的信号

由于其创建GL上下文的能力,渲染需要由GlArea小部件驱动。

需要连接realizeresizerender信号。在将闭包附加到GlArea::connect_realize()之后,在调用make_current()之后创建[GlRenderContext]和[GlRenderCallback](否则将无法“绑定”到当前GlArea GL上下文)

let gfx_context: Rc<RefCell<Option<GlRenderContext<RenderColorFormat, RenderDepthFormat>>>> = Rc::new(RefCell::new(None));

let render_callback: Rc<RefCell<Option<SimpleRenderCallback>>> = Rc::new(RefCell::new(None));

let glarea = gtk::GLArea::new();

glarea.connect_realize({
	let gfx_context = gfx_context.clone();
	let render_callback = render_callback.clone();

	move |widget| {
		if widget.get_realized() {
			widget.make_current();
		}

		let allocation = widget.get_allocation();

		let mut new_context =
			gfx_gtk::GlRenderContext::new(
			MSAA,
			allocation.width,
			allocation.height,
			None).ok();
		if let Some(ref mut new_context) = new_context {
			let ref vp = new_context.viewport();
			let ref mut ctx = new_context.gfx_context_mut();
			*render_callback.borrow_mut() = SimpleRenderCallback::new(ctx, vp).ok();
		}
		*gfx_context.borrow_mut() = new_context;
	}
});

glarea.connect_resize({
	let gfx_context = gfx_context.clone();
	let render_callback = render_callback.clone();

	move |_widget, width, height| {
		if let Some(ref mut context) = *gfx_context.borrow_mut() {
			if let Some(ref mut render_callback) = *render_callback.borrow_mut() {
				context.resize(width, height, Some(render_callback)).ok();
			}
		}
	}
});

glarea.connect_render({
	let gfx_context = gfx_context.clone();
	let render_callback = render_callback.clone();

	move |_widget, _gl_context| {
		if let Some(ref mut context) = *gfx_context.borrow_mut() {
			if let Some(ref mut render_callback) = *render_callback.borrow_mut() {
				context.with_gfx(render_callback);
			}
		}

		Inhibit(false)
	}
});

之后,每次Gtk刷新GlArea内容时,它将调用render_callback来绘制自己。

请参阅examples/setup.rs中的简单交互式渲染示例。运行它时,使用cargo run --example setup,它应该看起来像这样

Screenshot 1

© 2018 Nico Orru https://www.itadinanta.net

依赖关系

~13MB
~326K SLoC