原地址: github.com/glium/glium/

创建项目

首先, 创建一个新项目:

cargo new --bin my_project
cd my_project

在你刚创建的目录下的 Cargo.toml 文件中含有项目的元数据, src/main.rs 文件包含了Rust的源代码. 如果在目录下的文件不是 src/main.rs 而是 src/lib.rs , 说明你忘了输入 --bin 选项; 只要将 src/lib.rs 重命名为 src/main.rs 就可以了.

Cargo.toml 文件中添加如下依赖, 以在项目中导入glium库:

[dependencies]
glium = "*"

在使用依赖库之前, 需要在 src/main.rs 中添加如下代码以导入库:

#[macro_use]
extern crate glium;

fn main() {
}

是时候开始填满 main 函数了!

创建窗口

创建图形应用的第一步就是创建一个窗口. 如果你熟悉OpenGL那一套, 你应该了解其中的复杂程度. 无论是创建窗口还是创建上下文(Context), 在不同平台下的你要写的代码是不一样的, 唯一不变的是: 它非常无聊. 幸运的是, 这正是 glutin 库所擅长的东西.

使用glutin初始化OpenGL窗口需要经过如下几步:

  1. 创建 EventsLoop 用于处理窗口和设备的事件.
  2. 使用 glium::glutin::WindowBuilder::new() 指定窗口的参数. 这些参数与OpenGL无关, 而是窗口特有的属性.
  3. 使用glium::glutin::ContextBuilder::new()指定上下文(Context)参数. 我们可以在这里设置OpenGL特定的属性, 例如垂直同步与多重采样.
  4. 创建OpenGL窗口(在glium中称为 Display): glium::Display::new(window, context, &events_loop).unwrap() 这句代码使用给定的窗口和上下文创建了一个Dispaly, 并且使用所给的events_loop注册窗口.

fn main() {
use glium::glutin;

let mut events_loop = glutin::EventsLoop::new();
let window = glutin::WindowBuilder::new();
let context = glutin::ContextBuilder::new();
let display = glium::Display::new(window, context, &events_loop).unwrap();
}

但是有一个问题: 在窗口创建完成时, 我们的main函数就退出了, 导致 display 的析构函数关闭了窗口. 为了避免这个问题, 我们需要创建一个无限循环, 直到收到 CloseRequested 事件为止:

let mut closed = false;
while !closed {
// 列出由应用生成的事件并等待接收
events_loop.poll_events(|ev| {
match ev {
glutin::Event::WindowEvent { event, .. } => match event {
glutin::WindowEvent::CloseRequested => closed = true,
_ => (),
},
_ => (),
}
});
}

虽然, 这段代码将导致CPU占用率达到100%, 但是已经解决了上面所说的问题. 在实际的应用程序中, 你应当使用垂直同步或者在每次循环结束时sleep几毫秒, 不过这是之后要考虑的事了.

你现在可以运行 cargo run. 在Cargo下载完glium及其依赖并编译好之后, 你就能看见一个还过得去的小窗口了.

清除颜色

然而, 窗口里的内容并不怎么吸引人. 它也许是一片空白, 或者是一张随机的图片, 也可能是一些雪花, 这取决于你使用什么系统. 我们需要在窗口内绘制图形, 因此系统并不需要将窗口内的颜色初始化为某个特定的值.

Glium和OpenGL的API就像Windows下的画笔工具. 首先我们有一幅空白的画布, 我们可以在上面画一个又一个图形. 到你觉得满意为止. 和绘图软体不一样的是, 你不想你的用户看见绘画的过程. 他们能看见的应该只有最终的结果.

glium使用 Frame 对象来实现这一机制. 如果你打算在窗口中绘制图形, 首先应该调用 display.draw() 方法来创建一个 Frame:

let mut target = display.draw();

之后, 我们就能将 target 作为画布(drawing surface). OpenGL和glium提供的一个操作就是使用给定的颜色填充画布. 这正是我们要做的.

target.clear_color(0.0, 0.0, 1.0, 1.0);

注意: 我们需要先导入 Surface trait, 然后才能使用这个函数:

use glium::Surface;

我们传递给 clear_color 的四个值表示颜色的四个组成部分: 红, 绿, 蓝和透明度. 取值范围为[0.0, 1.0]. 这里我们选择的是不透明的蓝色.

正如我之前解释的, 现在用户没法在屏幕上看见蓝色. 如果我们是在写一个真正的应用的话, 我们也许会画上角色, 武器, 地面, 天空等等. 但是在这个指南中, 我们做到这一步就足够了:

target.finish().unwrap();

finish() 函数意味著我们结束了绘制. 它将销毁 Frame 对象, 并将画布复制到窗口上. 现在, 我们的窗口被一片蓝色填满了.

以下是所有的代码:

fn main() {
use glium::{glutin, Surface};

let mut events_loop = glium::glutin::EventsLoop::new();
let window = glium::glutin::WindowBuilder::new();
let context = glium::glutin::ContextBuilder::new();
let display = glium::Display::new(window, context, &events_loop).unwrap();

let mut closed = false;
while !closed {
let mut target = display.draw();
target.clear_color(0.0, 0.0, 1.0, 1.0);
target.finish().unwrap();

events_loop.poll_events(|ev| {
match ev {
glutin::Event::WindowEvent { event, .. } => match event {
glutin::WindowEvent::CloseRequested => closed = true,
_ => (),
},
_ => (),
}
});
}
}

推荐阅读:

相关文章