Draft a first working version 🎉
This commit is contained in:
parent
55275d7b05
commit
32c735ba36
|
@ -35,7 +35,13 @@ fn main() -> Result<(), String> {
|
||||||
context.window().request_redraw();
|
context.window().request_redraw();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// Enable auto-conversion from/to sRGB
|
||||||
gl.enable(glow::FRAMEBUFFER_SRGB);
|
gl.enable(glow::FRAMEBUFFER_SRGB);
|
||||||
|
|
||||||
|
// Enable alpha blending
|
||||||
|
gl.enable(glow::BLEND);
|
||||||
|
gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
gl.clear_color(0.4, 0.4, 0.4, 1.0);
|
gl.clear_color(0.4, 0.4, 0.4, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,13 +57,22 @@ fn main() -> Result<(), String> {
|
||||||
} => {
|
} => {
|
||||||
context.resize(new_size);
|
context.resize(new_size);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl.viewport(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
new_size.width as _,
|
||||||
|
new_size.height as _,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
size = new_size;
|
size = new_size;
|
||||||
}
|
}
|
||||||
glutin::event::Event::RedrawRequested { .. } => {
|
glutin::event::Event::RedrawRequested { .. } => {
|
||||||
unsafe { gl.clear(glow::COLOR_BUFFER_BIT) }
|
unsafe { gl.clear(glow::COLOR_BUFFER_BIT) }
|
||||||
|
|
||||||
glyph_brush.queue(Section {
|
glyph_brush.queue(Section {
|
||||||
text: "Hello wgpu_glyph!",
|
text: "Hello glow_glyph!",
|
||||||
screen_position: (30.0, 30.0),
|
screen_position: (30.0, 30.0),
|
||||||
color: [0.0, 0.0, 0.0, 1.0],
|
color: [0.0, 0.0, 0.0, 1.0],
|
||||||
scale: Scale { x: 40.0, y: 40.0 },
|
scale: Scale { x: 40.0, y: 40.0 },
|
||||||
|
@ -66,7 +81,7 @@ fn main() -> Result<(), String> {
|
||||||
});
|
});
|
||||||
|
|
||||||
glyph_brush.queue(Section {
|
glyph_brush.queue(Section {
|
||||||
text: "Hello wgpu_glyph!",
|
text: "Hello glow_glyph!",
|
||||||
screen_position: (30.0, 90.0),
|
screen_position: (30.0, 90.0),
|
||||||
color: [1.0, 1.0, 1.0, 1.0],
|
color: [1.0, 1.0, 1.0, 1.0],
|
||||||
scale: Scale { x: 40.0, y: 40.0 },
|
scale: Scale { x: 40.0, y: 40.0 },
|
||||||
|
|
126
src/pipeline.rs
126
src/pipeline.rs
|
@ -9,6 +9,7 @@ use glyph_brush::rusttype::{point, Rect};
|
||||||
pub struct Pipeline {
|
pub struct Pipeline {
|
||||||
sampler: <glow::Context as HasContext>::Sampler,
|
sampler: <glow::Context as HasContext>::Sampler,
|
||||||
program: <glow::Context as HasContext>::Program,
|
program: <glow::Context as HasContext>::Program,
|
||||||
|
vertex_array: <glow::Context as HasContext>::VertexArray,
|
||||||
instances: <glow::Context as HasContext>::Buffer,
|
instances: <glow::Context as HasContext>::Buffer,
|
||||||
cache: Cache,
|
cache: Cache,
|
||||||
current_instances: usize,
|
current_instances: usize,
|
||||||
|
@ -25,7 +26,7 @@ impl Pipeline {
|
||||||
let sampler =
|
let sampler =
|
||||||
unsafe { gl.create_sampler().expect("Create glyph sampler") };
|
unsafe { gl.create_sampler().expect("Create glyph sampler") };
|
||||||
|
|
||||||
let cache = Cache::new(gl, cache_width, cache_height);
|
let cache = unsafe { Cache::new(gl, cache_width, cache_height) };
|
||||||
|
|
||||||
let program = unsafe {
|
let program = unsafe {
|
||||||
create_program(
|
create_program(
|
||||||
|
@ -40,17 +41,18 @@ impl Pipeline {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let instances =
|
let (vertex_array, instances) =
|
||||||
unsafe { gl.create_buffer().expect("Create instance buffer") };
|
unsafe { create_instance_buffer(gl, Instance::INITIAL_AMOUNT) };
|
||||||
|
|
||||||
Pipeline {
|
Pipeline {
|
||||||
sampler,
|
sampler,
|
||||||
program,
|
program,
|
||||||
cache,
|
cache,
|
||||||
|
vertex_array,
|
||||||
instances,
|
instances,
|
||||||
current_instances: 0,
|
current_instances: 0,
|
||||||
supported_instances: Instance::INITIAL_AMOUNT,
|
supported_instances: Instance::INITIAL_AMOUNT,
|
||||||
current_transform: [0.0; 16],
|
current_transform: IDENTITY_MATRIX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +62,36 @@ impl Pipeline {
|
||||||
transform: [f32; 16],
|
transform: [f32; 16],
|
||||||
region: Option<Region>,
|
region: Option<Region>,
|
||||||
) {
|
) {
|
||||||
|
unsafe {
|
||||||
|
gl.use_program(Some(self.program));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.current_transform != transform {
|
||||||
|
unsafe {
|
||||||
|
gl.uniform_matrix_4_f32_slice(Some(0), false, &transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current_transform = transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl.active_texture(glow::TEXTURE0);
|
||||||
|
gl.bind_texture(glow::TEXTURE_2D, Some(self.cache.texture));
|
||||||
|
gl.uniform_1_i32(Some(1), 0);
|
||||||
|
|
||||||
|
gl.bind_vertex_array(Some(self.vertex_array));
|
||||||
|
|
||||||
|
gl.draw_arrays_instanced(
|
||||||
|
glow::TRIANGLE_STRIP,
|
||||||
|
0,
|
||||||
|
4,
|
||||||
|
self.current_instances as i32,
|
||||||
|
);
|
||||||
|
|
||||||
|
gl.bind_vertex_array(None);
|
||||||
|
gl.bind_texture(glow::TEXTURE_2D, None);
|
||||||
|
gl.use_program(None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_cache(
|
pub fn update_cache(
|
||||||
|
@ -69,8 +101,10 @@ impl Pipeline {
|
||||||
size: [u16; 2],
|
size: [u16; 2],
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) {
|
) {
|
||||||
|
unsafe {
|
||||||
self.cache.update(gl, offset, size, data);
|
self.cache.update(gl, offset, size, data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn increase_cache_size(
|
pub fn increase_cache_size(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -78,8 +112,12 @@ impl Pipeline {
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) {
|
) {
|
||||||
|
unsafe {
|
||||||
|
self.cache.destroy(gl);
|
||||||
|
|
||||||
self.cache = Cache::new(gl, width, height);
|
self.cache = Cache::new(gl, width, height);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn upload(&mut self, gl: &glow::Context, instances: &[Instance]) {
|
pub fn upload(&mut self, gl: &glow::Context, instances: &[Instance]) {
|
||||||
if instances.is_empty() {
|
if instances.is_empty() {
|
||||||
|
@ -88,12 +126,28 @@ impl Pipeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
if instances.len() > self.supported_instances {
|
if instances.len() > self.supported_instances {
|
||||||
// TODO
|
unsafe {
|
||||||
|
gl.delete_buffer(self.instances);
|
||||||
|
gl.delete_vertex_array(self.vertex_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (new_vertex_array, new_instances) =
|
||||||
|
unsafe { create_instance_buffer(gl, instances.len()) };
|
||||||
|
|
||||||
|
self.vertex_array = new_vertex_array;
|
||||||
|
self.instances = new_instances;
|
||||||
self.supported_instances = instances.len();
|
self.supported_instances = instances.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
unsafe {
|
||||||
|
gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.instances));
|
||||||
|
gl.buffer_sub_data_u8_slice(
|
||||||
|
glow::ARRAY_BUFFER,
|
||||||
|
0,
|
||||||
|
bytemuck::cast_slice(instances),
|
||||||
|
);
|
||||||
|
gl.bind_buffer(glow::ARRAY_BUFFER, None);
|
||||||
|
}
|
||||||
|
|
||||||
self.current_instances = instances.len();
|
self.current_instances = instances.len();
|
||||||
}
|
}
|
||||||
|
@ -219,3 +273,63 @@ unsafe fn create_program(
|
||||||
|
|
||||||
program
|
program
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn create_instance_buffer(
|
||||||
|
gl: &glow::Context,
|
||||||
|
size: usize,
|
||||||
|
) -> (
|
||||||
|
<glow::Context as HasContext>::VertexArray,
|
||||||
|
<glow::Context as HasContext>::Buffer,
|
||||||
|
) {
|
||||||
|
let vertex_array = gl.create_vertex_array().expect("Create vertex array");
|
||||||
|
let buffer = gl.create_buffer().expect("Create instance buffer");
|
||||||
|
|
||||||
|
gl.bind_vertex_array(Some(vertex_array));
|
||||||
|
gl.bind_buffer(glow::ARRAY_BUFFER, Some(buffer));
|
||||||
|
gl.buffer_data_size(
|
||||||
|
glow::ARRAY_BUFFER,
|
||||||
|
(size * std::mem::size_of::<Instance>()) as i32,
|
||||||
|
glow::DYNAMIC_DRAW,
|
||||||
|
);
|
||||||
|
|
||||||
|
let stride = std::mem::size_of::<Instance>() as i32;
|
||||||
|
|
||||||
|
gl.enable_vertex_attrib_array(0);
|
||||||
|
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, stride, 0);
|
||||||
|
gl.vertex_attrib_divisor(0, 1);
|
||||||
|
|
||||||
|
gl.enable_vertex_attrib_array(1);
|
||||||
|
gl.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, stride, 4 * 3);
|
||||||
|
gl.vertex_attrib_divisor(1, 1);
|
||||||
|
|
||||||
|
gl.enable_vertex_attrib_array(2);
|
||||||
|
gl.vertex_attrib_pointer_f32(2, 2, glow::FLOAT, false, stride, 4 * (3 + 2));
|
||||||
|
gl.vertex_attrib_divisor(2, 1);
|
||||||
|
|
||||||
|
gl.enable_vertex_attrib_array(3);
|
||||||
|
gl.vertex_attrib_pointer_f32(
|
||||||
|
3,
|
||||||
|
2,
|
||||||
|
glow::FLOAT,
|
||||||
|
false,
|
||||||
|
stride,
|
||||||
|
4 * (3 + 2 + 2),
|
||||||
|
);
|
||||||
|
gl.vertex_attrib_divisor(3, 1);
|
||||||
|
|
||||||
|
gl.enable_vertex_attrib_array(4);
|
||||||
|
gl.vertex_attrib_pointer_f32(
|
||||||
|
4,
|
||||||
|
4,
|
||||||
|
glow::FLOAT,
|
||||||
|
false,
|
||||||
|
stride,
|
||||||
|
4 * (3 + 2 + 2 + 2),
|
||||||
|
);
|
||||||
|
gl.vertex_attrib_divisor(4, 1);
|
||||||
|
|
||||||
|
gl.bind_vertex_array(None);
|
||||||
|
gl.bind_buffer(glow::ARRAY_BUFFER, None);
|
||||||
|
|
||||||
|
(vertex_array, buffer)
|
||||||
|
}
|
||||||
|
|
|
@ -1,15 +1,55 @@
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
|
|
||||||
pub struct Cache {
|
pub struct Cache {
|
||||||
texture: <glow::Context as HasContext>::Texture,
|
pub(crate) texture: <glow::Context as HasContext>::Texture,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cache {
|
impl Cache {
|
||||||
pub fn new(gl: &glow::Context, width: u32, height: u32) -> Cache {
|
pub unsafe fn new(gl: &glow::Context, width: u32, height: u32) -> Cache {
|
||||||
let texture = unsafe {
|
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
|
||||||
let handle = gl.create_texture().expect("Create glyph cache texture");
|
|
||||||
|
|
||||||
gl.tex_storage_2d(handle, 1, glow::R8, width as i32, height as i32);
|
let texture = {
|
||||||
|
let handle =
|
||||||
|
gl.create_texture().expect("Create glyph cache texture");
|
||||||
|
|
||||||
|
gl.bind_texture(glow::TEXTURE_2D, Some(handle));
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
gl.object_label(glow::TEXTURE, handle, Some("Glyph cache"));
|
||||||
|
|
||||||
|
gl.tex_parameter_i32(
|
||||||
|
glow::TEXTURE_2D,
|
||||||
|
glow::TEXTURE_WRAP_S,
|
||||||
|
glow::CLAMP_TO_EDGE as i32,
|
||||||
|
);
|
||||||
|
gl.tex_parameter_i32(
|
||||||
|
glow::TEXTURE_2D,
|
||||||
|
glow::TEXTURE_WRAP_T,
|
||||||
|
glow::CLAMP_TO_EDGE as i32,
|
||||||
|
);
|
||||||
|
gl.tex_parameter_i32(
|
||||||
|
glow::TEXTURE_2D,
|
||||||
|
glow::TEXTURE_MIN_FILTER,
|
||||||
|
glow::LINEAR as i32,
|
||||||
|
);
|
||||||
|
gl.tex_parameter_i32(
|
||||||
|
glow::TEXTURE_2D,
|
||||||
|
glow::TEXTURE_MAG_FILTER,
|
||||||
|
glow::LINEAR as i32,
|
||||||
|
);
|
||||||
|
|
||||||
|
gl.tex_image_2d(
|
||||||
|
glow::TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
glow::R8 as i32,
|
||||||
|
width as i32,
|
||||||
|
height as i32,
|
||||||
|
0,
|
||||||
|
glow::RED,
|
||||||
|
glow::UNSIGNED_BYTE,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
gl.bind_texture(glow::TEXTURE_2D, None);
|
||||||
|
|
||||||
handle
|
handle
|
||||||
};
|
};
|
||||||
|
@ -17,7 +57,34 @@ impl Cache {
|
||||||
Cache { texture }
|
Cache { texture }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self, gl: &glow::Context, offset: [u16; 2], size: [u16; 2], data: &[u8]) {
|
pub unsafe fn update(
|
||||||
// TODO
|
&self,
|
||||||
|
gl: &glow::Context,
|
||||||
|
offset: [u16; 2],
|
||||||
|
size: [u16; 2],
|
||||||
|
data: &[u8],
|
||||||
|
) {
|
||||||
|
let [offset_x, offset_y] = offset;
|
||||||
|
let [width, height] = size;
|
||||||
|
|
||||||
|
gl.bind_texture(glow::TEXTURE_2D, Some(self.texture));
|
||||||
|
|
||||||
|
gl.tex_sub_image_2d_u8_slice(
|
||||||
|
glow::TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
i32::from(offset_x),
|
||||||
|
i32::from(offset_y),
|
||||||
|
i32::from(width),
|
||||||
|
i32::from(height),
|
||||||
|
glow::RED,
|
||||||
|
glow::UNSIGNED_BYTE,
|
||||||
|
Some(data),
|
||||||
|
);
|
||||||
|
|
||||||
|
gl.bind_texture(glow::TEXTURE_2D, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn destroy(&self, gl: &glow::Context) {
|
||||||
|
gl.delete_texture(self.texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
layout(location = 0) uniform mat4 transform;
|
layout(location = 0) uniform mat4 transform;
|
||||||
|
|
||||||
in vec3 left_top;
|
layout(location = 0) in vec3 left_top;
|
||||||
in vec2 right_bottom;
|
layout(location = 1) in vec2 right_bottom;
|
||||||
in vec2 tex_left_top;
|
layout(location = 2) in vec2 tex_left_top;
|
||||||
in vec2 tex_right_bottom;
|
layout(location = 3) in vec2 tex_right_bottom;
|
||||||
in vec4 color;
|
layout(location = 4) in vec4 color;
|
||||||
|
|
||||||
out vec2 f_tex_pos;
|
out vec2 f_tex_pos;
|
||||||
out vec4 f_color;
|
out vec4 f_color;
|
||||||
|
|
Loading…
Reference in New Issue